[技术问答] 排序算法-综述

[复制链接]
 楼主| 萧洛毫 发表于 2019-4-30 22:03 | 显示全部楼层 |阅读模式
1、冒泡排序算法:
冒泡排序算法是最简单也是最基本的排序算法之一,算法的原理为如下:
原理:将数据当中的每一个元素与之后的元素进行对比,如果当前元素比序列后的元素的值小,则交换两者的顺序,依次类推,直到最后一个数据完成排序即可!
时间复杂度:O(n2)
API实现如下(两层for循环嵌套实现):
  1. int BubbleSort(int *In, int N)
  2. {
  3.     int temp;
  4.     for (int i = 0; i < N; i++) {
  5.         for (int j = i + 1; j < N; j++) {
  6.             if (In[i] > In[j]) {
  7.                 temp = In[i];
  8.                 In[i] = In[j];
  9.                 In[j] = temp;
  10.             }
  11.         }
  12.     }
  13.     return 1;
  14. }


 楼主| 萧洛毫 发表于 2019-4-30 22:03 | 显示全部楼层
2、插入排序算法:

插入排序算法是最基本的排序算法之一,少量数据的排序,其效率较高,算法的原理为如下:

原理:从第一个数值开始排序,在每一个P循环之后,0-P之间的所有元素都是已经完成排序了,P之后的第一个数据作为插值,和前面的顺序序列对比并插入正确的位置!

时间复杂度:O(n2),对于基本排列好序列的数据,插入排序算法的时间复杂度为O(n)。

API实现如下:

  1. int InsertSort(int *In, int N)
  2. {
  3.     int P, i, temp;
  4.     for (P = 1; P < N; P++) {
  5.         temp = In[P];
  6.         for (i = P; i > 0 && temp < In[i - 1]; i--) {
  7.             In[i] = In[i - 1];
  8.         }
  9.         In[i] = temp;
  10.     }
  11.     return 1;
  12. }
 楼主| 萧洛毫 发表于 2019-4-30 22:03 | 显示全部楼层
3、希尔排序算法:
希尔排序算法的平均时间复杂度较低,算法的原理如下:
原理:算法在运行的过程中,每次将前面的数据与其间隔stride步长位置的数据进行对比,完成当前stride的全部对比之后,将stride缩小为原来的一半,以此类推,最后stride为1,这个时候对比的就是相邻的元素,对比完成,序列同时完成了排序。
时间复杂度:O(n*log(n))
API_0实现如下(常规的希尔序列初始增量:N/2. N为数据的长度):
  1. int ShellSort(int *In, int N)
  2. {
  3.     int i, j, stride,Temp;
  4.     /* 这里需要注意的是,stride最终的结果为0:当stride=1时,stride/=2得到的stride=floor(0.5)=0,所以循环退出 */
  5.     for (stride = N / 2; stride > 0; stride /= 2) {
  6.         for (i = stride; i < N; i++) {
  7.             Temp = In[i];
  8.             for (j = i; j >= stride && Temp < In[j - stride] ; j -= stride) {
  9.                     In[j] = In[j - stride];
  10.             }
  11.             In[j] = Temp;
  12.         }
  13.     }
  14.     return 1;
  15. }
API_1实现如下(希尔Hibbard增量序列:Hibbard:{1, 3, ..., 2^k-1})
注:这是一种冲破二次时间屏障的算法
  1. int ShellSort_Hibbard(int *In, int N) // 时间复杂度最坏的情况为o(N^3/2)
  2. {
  3.     int i, j, stride, Temp;
  4.     int k = log2(N / 2 + 1);
  5.     // printf("The k is:%d\n", k);
  6.     /* 这里需要注意的是,stride最终的结果为0:当stride=1时,stride/=2得到的stride=floor(0.5)=0,所以循环退出 */
  7.     for (stride = (2<<k) - 1; stride > 0 && k >= 1; stride = (1<<k) - 1) { // 注意这里的左移运算的优先级低于减法的优先级,所以要打上括号
  8.         // printf("The stride is:%d\n", stride);
  9.         for (i = stride; i < N; i++) {
  10.             Temp = In[i];
  11.             for (j = i; j >= stride && Temp < In[j - stride]; j -= stride) {
  12.                 In[j] = In[j - stride];
  13.             }
  14.             In[j] = Temp;
  15.         }
  16.         k -= 1;
  17.     }
  18.     return 1;
  19. }


 楼主| 萧洛毫 发表于 2019-4-30 22:05 | 显示全部楼层
4、选择快速排序算法:
快速排序算法的平均时间复杂度低,比较适合大量数据的排序算法,算法的原理如下:
原理:快速排序算法的情况和归并排序算法比较相似!详细原理参考这里:https://www.jianshu.com/p/7631d95fdb0b
时间复杂度:O(n*log(n))
API实现如下:
  1. #define Cutoff 3
  2. void Swap(int *A, int *B)
  3. {
  4.     int Temp;
  5.     Temp = *A;
  6.     *A = *B;
  7.     *B = Temp;
  8. }
  9. int Median3(int A[], int left, int right) // 寻找枢纽值
  10. {
  11.     int center = (left + right) / 2;
  12.     int Temp;

  13.     if (A[left] > A[center])
  14.         Swap(&A[left], &A[center]);
  15.     if (A[left] > A[right])
  16.         Swap(&A[left], &A[right]);
  17.     if (A[center] > A[right])
  18.         Swap(&A[center], &A[right]);

  19.     Swap(&A[center], &A[right - 1]); // 将枢纽值保存在数组的边缘
  20.     return A[right - 1];  // return pivot-返回枢纽值
  21. }
  22. void QSort(int A[], int left, int right)
  23. {
  24.     int i, j;
  25.     int pivo;
  26.     if (left + Cutoff <= right) { // 小数组的处理交给插值排序的方法,速度比较快一些
  27.         pivo = Median3(A, left, right); // 枢纽值求解
  28.         i = left; j = right - 1;
  29.         for (;;)
  30.         {
  31.             while (A[++i] < pivo) { } // 分割策略
  32.             while (A[--j] > pivo) { } // 分割策略
  33.             if (i < j)
  34.                 Swap(&A[i], &A[j]);
  35.             else
  36.                 break;
  37.         }
  38.         Swap(&A[i], &A[right - 1]); // Swap函数属于外部调用,为了提高算法的效率可以直接显式写出代码,不用callSwap函数

  39.         QSort(A, left, i-1); // 分割之后的递归调用
  40.         QSort(A, i+1, right); // 分割之后的递归调用
  41.     }
  42.     else {
  43.         InsertSort(A + left, right - left + 1); // 插值排序算法
  44.     }

  45. }
  46. void QuickSort(int A[], int N)
  47. {
  48.     QSort(A, 0, N-1);
  49. }


 楼主| 萧洛毫 发表于 2019-4-30 22:06 | 显示全部楼层
5、堆排序算法:
堆排序算法的平均时间复杂度较低,算法的原理如下:
原理:堆排序算法主要使用了堆数据结构的特点,创建二叉堆,并进行堆排序,即可完成数据的排序。
时间复杂度:O(n*log(n))
API实现如下:
  1. #define LeftChild(i) (2*(i)+1)
  2. void PerDown(int A[], int i, int N) // 降过滤法完成二叉堆的生成
  3. {
  4.     int Child;
  5.     int Tmp;
  6.     for (Tmp = A[i]; LeftChild(i) < N; i = Child) {
  7.         Child = LeftChild(i);
  8.         if (Child != N - 1 && A[Child + 1] > A[Child])
  9.             Child++;
  10.         if (Tmp < A[Child])
  11.             A[i] = A[Child];
  12.         else
  13.             break;
  14.     }
  15.     A[i] = Tmp;
  16. }
  17. void Swap(int *A, int *B)
  18. {
  19.     int Temp;
  20.     Temp = *A;
  21.     *A = *B;
  22.     *B = Temp;
  23. }
  24. void HeapSort(int A[], int N)
  25. {
  26.     int i;
  27.     for (i = N / 2; i >= 0; i--) {
  28.         PerDown(A, i, N); // 创建二叉堆
  29.     }
  30.     for (i = N - 1; i > 0; i--)
  31.     {
  32.         Swap(&A[0], &A[i]); // Delet the Max Element
  33.         PerDown(A, 0, i);
  34.     }
  35. }


 楼主| 萧洛毫 发表于 2019-4-30 22:08 | 显示全部楼层
6、桶排序算法:
堆排序算法的平均时间复杂度较低,算法的原理如下:
原理:桶排序算法主要使用了类似于散列表的特点,将待排序的数据的数据内容统计起来,按照index桶的位置来确保数据的顺序问题,从而完成了桶排序的任务!
时间复杂度:O(n)
API实现如下:
  1. void BucketSort(int A[], int N, int MAX) // 对于排序小整数的情况,buckect桶排序算法非常的适合
  2. {
  3.     int *Bucket = (int *)malloc(sizeof(int)*MAX);
  4.     int index;
  5.     for (int i = 0; i < MAX; i++) {
  6.         *(Bucket + i) = 0;
  7.     }
  8.     for (int i = 0; i < N; i++) {
  9.         index = A[i];
  10.         Bucket[index] += 1;
  11.     }
  12.     index = 0;
  13.     for (int i = 0; i < MAX; i++) {
  14.         while (Bucket[i] != 0) {
  15.             A[index] = i;
  16.             index += 1;
  17.             Bucket[i] -= 1;
  18.         }
  19.     }
  20. }


jerow 发表于 2019-4-30 23:19 | 显示全部楼层
支持下,谢谢分享!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

53

主题

254

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部

53

主题

254

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部