zoukankan      html  css  js  c++  java
  • 排序算法总结

    回到数据结构与算法,再次把一些经典的排序算法的代码回顾一下。

    1. 插入排序

    可以想象手里有一副扑克牌,从左到右是{4, 3, 7, 1, 9}。一张一张来看。

    4

    4,3 排序有误。将3插入到4前,变成 3,4。

    3,4,7排序无误。

    3,4,7,1排序有误,将1插入到3前,变成1,3,4,7

    ......

    代码为:

    void swap(int &a, int & b)

    {

      int temp = a;

      a = b;

      b= temp;

    }

    void insertSort(int a[], int length)

    {

      for(int i=1;i<length;i++)

      {

        for(int j=i;i>=0;j--)

        {

          if(a[j-1]>a[j]) swap(a[j-1], a[j]);

        }

      }

    }

    特征:原地排序,空间复杂度为O(1)。平均时间复杂度为O(n2),最坏时间复杂度为O(n2)。排序是稳定的。

    当基本有序时,使用插入排序效率很高。

    2. 冒泡排序

    特点就是像冒泡泡一样,一点一点往前移动。总是将当前数与右边数相比,如果当前数更大就和右边的数交换,否则不交换。

    例如数组为{4, 3, 7, 1, 9}。

    第一轮:{3, 4, 1, 7, 9}

    第二轮:{3, 1, 4, 7, 9}

    第三轮:{1, 3, 4, 7, 9} 结束

    代码如下:

    void bubbleSort(int a[], int length)

    {

      int count = 1;

      while(count >0)

      {

        count = 0;

        for(int i=0;i<length-1;i++)

        {

          if(a[i]>a[i+1])

          {

            swap(a[i], a[i+!]);

            count++;

          }

        }

      }

    }

    特点:原地排序,空间复杂度为O(1)。时间复杂度为O(n2),最坏时间复杂度为O(n2)。排序是稳定的。

    3. 堆排序

    关于堆排序介绍众多,此处就不再放图了。主要就是不断交换父节点和子节点来维持有序。

    代码如下:

    void heapSort(int a[], int length)

    {

      //从最后一个父节点开始,初始化堆

      for(int i = len/2-1;i>=0;i--)

      {

        heapify(a, i, length);    

      }

      //然后不断将最大值与最后的子节点交换,得到有序序列

      for(int i=length-1;i>=0;i--)

      {

        swap(a[0], a[i]);

        heapify(a, 0, i);

      }

    }

    void heapify(int a[], int start, int end)

    {

      int father = start, son = 2*father + 1;

      while(son < end)

      {

        if(son + 1<end &&a[son] < a[son + 1] ) son++;

        if(a[father] > a[son]) break;

        else

        {

          swap(a[son], a[father]);

          father = son;

           son = father*2 + 1;

        }

      }

    }

    特点:原地排序,空间复杂度为O(1)。时间复杂度为O(nlogn),最好时间复杂度最坏时间复杂度都是O(nlogn)。为不稳定排序。

    适合求topK问题。

    4. 快速排序

    简单来说,就是一路从右往左扫掠,另一路从左往右扫掠,一旦遇到违反排序的,就交换。

    void quickSort(int a[], int start, int end)

    {

      if(start>=end) return;

      int pivot = onceSort(a, start, end);

      quickSort(a, start, pivot-1);

      quickSort(a, pivot+1, end);

    }

    int onceSort(int a[], int start, int end)

    {

      int i = start, j = end;

      while(i<j)

      {

        while(i<j && a[i]<a[j]) j--;

        if(i<j) swap(a[i], a[j]);

        while(i<j && a[i]<a[j]) i++;

        if(i<j) swap(a[i], a[j]);

      }

      return i;

    }

    特点:原地排序,空间复杂度为O(logn)。平均时间复杂度O(nlogn),最坏时间复杂度为O(n2)。排序不稳定。

    当数组基本有序时,时间复杂度反而会增加。因此一般在排序前先要打乱来保证高效。

    5. 归并排序

    典型的二分法排序。

    void mergeSort(int a[], const int length)

    {

      int help[length];

      merge(a, help, 0, length-1); 

    }

    void merge(int a[], int help[], int start, int end)

    {

      if(start>=end) return; 

      int mid = (start + end)/2;

      merge(a, help, start, mid);

      merge(a, help, mid+1, end);

      int l1 = start, l2 = mid, r1 = mid+1, r2 = end;

      int k = l1;

      while(l1<=l2 && r1<=r2)

      {

        if(a[l1]<a[r1])

          help[k++] = a[l1++];

        else

          help[k++] = a[r1++];

      }  

      while(l1<=l2)  

        help[k++] = a[l1++];

      while(r1<=r2)

        help[k++] = a[r1++];

      for(int k = l1;k<=r2;k++)

        a[k] = help[k];

    }

    特点:借助辅助数组,非原地排序。空间复杂度为O(n)。平均时间复杂度为O(nlogn),最坏时间复杂度也为O(nlogn),为稳定排序。

     

  • 相关阅读:
    Brighter3d无法渲染可导入REVIT渲染
    屏蔽优酷等视频网站片头广告
    REVIT机电管线支架族的创建
    如何显示链接的REVIT模型中的注释文字
    REVIT参数化自适应多边形拉伸
    REVIT族管理插件project family brower
    使用VMware虚拟磁盘管理工具调整磁盘大小
    硬件兼容性的陷阱,DrawIndexedPrimitiveUP的用法
    第二章 伤寒之意义(1)
    可变参数函数设计
  • 原文地址:https://www.cnblogs.com/corineru/p/11080477.html
Copyright © 2011-2022 走看看