• 排序


    2020.8.26    排序算法

    一.简单模板

    1.选择排序:时间复杂度o()

    每次找到最小的一个,然后与没排的第一个元素交换

    void choseSort(int arr[], int n) {

        int i, j;

        int min, temp;

        // 每次从未排序的部分选出一个最小的元素,最后一次只剩一个元素未排序

        // 此时实际上已经排好序,故只需要n-1次外层大循环

        for (i = 0; i < n - 1; ++i) {

            min = i;    // 假定未排序部分的第一个元素为最小的元素

            // 遍历剩下的部分,找到最小的元素

            for (j = i + 1; j < n; ++j) {

                if (arr[j] < arr[min]) {

                    min = j;

                }

            }

            // 如果第一个元素就是最小的元素,就不需要交换了

            if (min != i) {

                temp = arr[i];

                arr[i] = arr[min];

                arr[min] = temp;

            }

        }

    }

     

    2.冒泡排序:时间复杂度o()

    一步一步来,每个元素都只跟他后面一个比,大于就交换,任务就是将每一个元素送到末尾。但是存在有可能几轮就排序好了,但是还在比较,所以增加flag元素单标此次循环比较有没有移动。

     代码:

    void bubblingSort(int arr[], int n) {

        int i, j, temp;

        int flag = 0;   // flag用来校验每轮循环有没有移动元素,0为没有移动,1为移动

        // 每次将一个元素送到末尾,n个元素,执行n次

        for (i = 0; i < n; ++i) {

            flag = 0;

            // 之前的循环已经将i个元素送到末尾,不需要再次比较,故减去,因为跟后一个元素比较,为了避免溢出,故减一

            for (j = 0; j < n - i - 1; ++j) {

                // 如果当前的元素比后一个元素小,就交换

                if (arr[j] > arr[j + 1]) {

                    flag = 1;   // 有数据交换

                    temp = arr[j];

                    arr[j] = arr[j + 1];

                    arr[j + 1] = temp;

                }

            }

            // 没有数据交换,提前结束

            if (flag == 0) {

                break;

            }

        }

    }

     

    3.插入排序     时间复杂度o()

    将一个数放到一个有序队列中,从末尾开始一个个比较,大于往后移,直到找到合适的位置。

    代码:

    void insert_sort(int arr[], int len)
      {
        for (int i = 1; i < len; ++i)
        {
          if (arr[i] < arr[i - 1]) {
          int temp = arr[i];
          int j = i - 1;
          for (; j >= 0 && arr[j]>temp; --j) {
            arr[j + 1] = arr[j];//交换位置
          }
        arr[j + 1] = temp;
      }
    }
    }

    二、进阶模板

    1.快速排序    时间复杂度o()这个递归比非递归快是怎么回事????

     int partion(int a[], int left, int right)

     {

         //取最右边的元素作划分元素

         int temp = a[right];

         //记录 i = left, j = right

        int i = left, j = right-1;

         //循环直到左右指针相遇

         while(true)

          {

             //从左边开始扫描,当出现比划分元素大的元素,扫描停止

             while(temp > a[i])

              {

                 i++;

             }

            //从右边进行扫描,当出现比划分元素小的元素,扫描停止

            while(temp < a[j]  && j >= left)

             {

                 j--;

             }

              //如果 i >= j, 循环截止,下面的交换不执行

    • ·          if(i >= j) break;
    • ·          //交换停止时的元素
    • ·          swap(a[i], a[j]);
    • ·      }
    • ·      //交换该元素与划分元素
    • ·      swap(a[i], a[right]);
    • ·      Print(a, 0, 6);
    • ·      //printf("i = %d", i);
    • ·      //划分过程结束
    • ·      return i;
    • ·  }
    • ·  //快速排序

    递归实现:

    • ·  void qsort(int a[], int left, int right)
    • ·  {
    • ·      //排序完成,循环截止
    • ·      if(right <= left)
    • ·          return;
    • ·      //做划分
    • ·      int i = partion(a, left, right);
    • ·      //对左部分排序
    • ·      if(left < (i-1))
    • ·          printf("对%d~%d排序 ", left, i-1), qsort(a, left, i-1);

        //对右部分排序

              if(right > (i+1))

             printf("对%d~%d排序 ", i+1, right), qsort(a, i+1, right);

     }

     非递归实现:
    ·  void qsort(int a[], int left, int right)

    • ·  {
    • ·      int i;
    • ·      //定义栈s
    • ·      stack<int> s;
    • ·      //先判断栈是否为空
    • ·      while(!s.empty())
    • ·      {
    • ·          //若栈不为空,将栈中元素移出
    • ·          s.pop();
    • ·      }
    • ·      //将right入栈
    • ·      s.push(right);
    • ·      //将left入栈
    • ·      s.push(left);
    • ·      //while循环,当栈为空时,循环结束
    • ·      while(!s.empty())
    • ·      {
    • ·          //元素left出栈
    • ·          left = s.top(), s.pop();
    • ·          //元素right出栈
    • ·          right = s.top(), s.pop();
    • ·          //判断left与right的关系,如果left>=right,continue
    • ·          if(left >= right)
    • ·          {
    • ·              continue;
    • ·          }
    • ·          //作划分
    • ·          i = partion(a, left, right);
    • ·          //比较两个子数组的大小
    • ·          //将子数组中的较大者压入栈
    • ·          if((i-1-left) > (right-i-1))
    • ·          {
    • ·              s.push(i-1);
    • ·              s.push(left);
    • ·              s.push(i+1);
    • ·              s.push(right);
    • ·          }
    • ·          else
    • ·          {
    • ·              s.push(i+1);
    • ·              s.push(right);
    • ·              s.push(i-1);
    • ·              s.push(left);
    • ·          }
    • ·      }
    • ·  }

    三、例题

    题目描述

    输入 n(n<5000000 n为奇数) 个数字 ai(0<ai<109),输出这些数字的第 k 小的数。最小的数是第 0 小。

    输入格式

    输出格式

    输入输出样例

    输入 #1 

    5 1

    4 3 2 1 5

    输出 #1 

    2

    代码:

    #include<bits/stdc++.h>using namespace std;int x[5000005],k;void qsort(int l,int r){

    int i=l,j=r,mid=x[(l+r)/2];

    do

    {

    while(x[j]>mid)

    j--;

    while(x[i]<mid)

    i++;

    if(i<=j)

    {

    swap(x[i],x[j]);

    i++;

    j--;

    }

    }

    while(i<=j);

    //快排后数组被划分为三块: l<=j<=i<=r

    if(k<=j) qsort(l,j);//在左区间只需要搜左区间

    else if(i<=k) qsort(i,r);//在右区间只需要搜右区间

    else //如果在中间区间直接输出

    {

    printf("%d",x[j+1]);

    exit(0);

    }

    }int main(){

    int n;

    scanf("%d%d",&n,&k);

    for(int i=0;i<n;i++)

    scanf("%d",&x[i]);

    qsort(0,n-1);

    }

  • 相关阅读:
    Scala编程基础
    大数据学习环境搭建(CentOS6.9+Hadoop2.7.3+Hive1.2.1+Hbase1.3.1+Spark2.1.1)
    hadoop2.7.3编译,支持snappy、bzip2本地压缩
    ABAP非Unicode系统中字符串拼接(CONCATENATE)时吃字符问题
    Hadoop学习笔记
    HIVE开发总结
    中文字符截取乱码问题
    替换空字符NULL(字符编码为0的字符)
    Generate Time Data(普通日期主数据)
    Generate Time Data(财务日期主数据)
  • 原文地址:https://www.cnblogs.com/wtx2333/p/13574324.html