排序算法总结

来源:互联网 发布:江南大学网络教育好吗? 编辑:程序博客网 时间:2024/05/18 14:27

名字最好O(n)平均O(n)最坏O(n)时间复杂度是否与初始顺序有关是否稳定空间复杂度算法描述选择排序O(n^2)O(n^2)O(n^2)Yes     NoO(1)每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子文件的最后,直到全部记录排序完毕。常用的选择排序方法有直接选择排序和堆排序直接插入O(n)O(n^2)O(n^2)YesYesO(1)每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中的适当位置,直到全部记录插入完成为止。冒泡排序O(n)O(n^2)O(n^2) YesO(1)两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序 的记录为止。应用交换排序基本思想的主要排序方法有:冒泡排序和快速排序。希尔排序O(n)O(nlogn)O(n^s)(1<s<2)    No    NoO(1)插入排序相同距离的元素做插入排序。快速排序O(nlogn)O(nlogn)
O(n^2)
每次划分都是最大程度不对称:(n-1)+0
Yes    NoO(logn)交换排序。分治法。在数组中任意选一个记录作为基准(pivot),以此基准将当前无序区划分为左右两个较小的子区间,使左区间的所有数都小于等于pivot,右边区间的数都大于等于pivot,而pivot则位于正确的位置上,不用参加后续的排序。堆排序O(nlogn)O(nlogn)O(nlogn)     NoO(1)选择排序。 堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,方便选取最大(最小)元素。 将 R[1..n]构造为初始堆; - 每一趟排序的基本操作:将当前 无序区的堆顶记录 R[1] 和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。归并排序O(nlogn)O(nlogn)O(nlogn) YesO(n)归并是指将若干个已排序的子文件合并成一个有序的文件。分治法,自顶向下。


当文件为正序时,直接插入和冒泡均最佳。

在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持 不变,该排序方法是稳定的;若具有相同关键字的记录之间的相对次序发生变化,则称这种排序方法是不稳定 的。

直接选择排序:
第 i 趟排序:第i趟排序开始时,当前有序区和无序区分别为 R[1..i-1]和 R[i..n][1≤i≤n-1]。该趟排序从当前 无序区中选出关键字最小的记录 R[k],将它与无序区的第 i 个记录 R[i]交换,使 R[1..i]和 R[i+1..n]分别变为 记录个数增加 1 个的新有序区和记录个数减少 1 个的新无序区。

直接插入排序:
每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中的适当位置,直到全部记录插入完成为止。
直接插入排序的基本操作是将当前无序区的第 1 个记录 R[i]插人到有序区 R[1..i-1]中适当的位置上,使 R[1..i]变为新的有序区。
像玩扑克牌一样,从无序的牌堆顶部取走一张牌,使之放在左手有序牌的正确位置上,就需要从左向右或者从右向左遍历。



冒泡排序:
两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序 的记录为止。应用交换排序基本思想的主要排序方法有:冒泡排序和快速排序。
因为每一趟排序都使有序区增加了一个气泡,在经过 n-1 趟排序之后,有序区中就有 n-1 个气泡,而无序区中气 泡的重量总是大于等于有序区中气泡的重量,所以整个冒泡排序过程至多需要进行 n-1 趟排序
flag标记表示是否存在逆序。

每趟扫描仅能使最重气泡"下沉"一个位置,因此使位于顶端的最重气泡下沉到底部时,需做 n-1 趟扫描。


快速排序:
方法1:
   方法2:    

过程:分解-》求解-》组合
划分的步骤:
1.两个指针i,j分别指向数组的上界和下界i=left,j=right,选取第一个元素a[left],将值保存在pivot中。
2.j从right处自右向左扫描,直到找到第一个小于pivot的元素a[j],然后将a[j]与a[i]交换,使关键字小宇pivot的移到了基准的左边,交换后a[j]的值就是pivot;然后令i从i+1的位置开始从左向右扫描,直到找到第一个大于pivot的元素a[i],交换a[i]与a[j],使关键字大于pivot的元素放到了pivot的右边,此时a[i]内的元素就是pivot;然后令j从j-1处从右向左扫描,如此交替改变扫描方向,直到i=j时,i便是pivot的最终位置,将pivot的放到此位置就完成了一次划分。
求解:
根据划分,以pivot的位置把数组分成两个部分,依次调用快排
组合:
将上面两部分的函数返回结果直接连接起来就得到了最终结果。


希尔排序:
先取一个小于 n 的整数 d1 作为第一个增量,把文件的全部记录分成 d1 个组。所有距离为 d1 的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量 d2<d1重复上述的分组和排序,直到所取的增量dt=1(dt<dt-1<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

好的增量序列的共同特征:
• 最后一个增量必须为 1;                                                    d/3+1
• 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。


堆排序:
n 个关键字序列 K1,K2,…,Kn 称为堆,当且仅当该序列满足如下性质(简称为堆性质):
 
若将此序列所存储的向量 R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉 树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。

根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆。 根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆。

堆排序与直接选择排序的比较:
在直接选择排序中,R[1..n]中选出最小元素需要做n-1次比较,然后在 R[2..n]中选出关键字最小的记录,又需要做 n-2 次比较。事实上,后面的 n-2 次比较中,有许多比较可能在前面的 n-1 次比较中已经做过,有一些重复比较,堆排序可以根据树形结构保存部分比较结果,减少比较次数。

大根堆排序的基本思想:
1.先将初始数组构成一个大根堆,此堆为初始的无序区(层序遍历无序)。
2.将堆顶最大的元素与无序区的最后一个记录R[n]对换,得到新的无序区R[1..n-1]和有序区R[n]。满足无序区的所有元素小于R[n]。
3.重新调整无序区元素使之构成大根堆,再将R[1,...,n-1]中最大的元素R[1]与R[n-1]对调。得到新的无序区R[1..n-2]和有序区R[n-1,...,n-1].同样将R[1,...,n-2]调整成大根堆,知道无序区只有一个元素为止。

完全二叉树的基本性质:
数组中有n个元素,i是节点,1 <= i <= n/2 就是说数组的后一半元素都是叶子节点。
i的父节点位置:i/2
 i左子节点位置:i*2
 i右子节点位置:i*2 + 1


在重建堆的过程中,只用调整比父节点大的子节点所在的那部分子树。

由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件

归并排序:

设归并排序的当前区间是R[low..high],分治法的三个步骤是:
• 分解:将当前区间一分为二,即求分裂点
• 求解:递归地对两个子区间 R[low..mid]和 R[mid+1..high]进行归并排序;
• 组合:将已排序的两个子区间 R[low..mid]和 R[mid+1..high]归并为一个有序的区间 R[low..high]。
递归的终结条件:子区间长度为 1(一个记录自然有序)。



桶排序:
桶排序的平均时间复杂度是线性的,即 O(n)。但最坏情况仍有可能是 O(n2)。
箱排序只适用于关键字取值范围较小的情况,否则所需箱子的数目 m 太多导致浪费存储空间和计算时间。

伪代码:



基数排序:
基数排序的基本思想是:从低位到高位依次对 Kj(j=d-1,d-2,…,0)进行箱排序。在 d 趟箱排序中,所需的箱 子数就是基数 rd,这就是"基数排序"名称的由来。
箱排序也称桶排序(Bucket Sort),其基本思想是:设置若干个箱子,依次扫描待排序的记录 R[0],R[1],…,R[n-1],把关键字等于 k 的记录全都装入到第 k 个箱子里(分配),然后按序号依次将各非空的 箱子首尾连接起来(收集)。
基数排序的时间是线性的(即 O(n))。 基数排序所需的辅助存储空间为 O(n+rd)。 基数排序是稳定的。



1.首先计算出数组中最大的数的数的位数
2.桶的个数设为10,即从0到9
3.然后从数的个位开始,数组里面所有数根据个位的数字,决定该数映射到那个桶中,统计每个桶中元素的个数count[i]。
4.让每个桶的计数变为从第1个桶到该桶之间所有元素的个数。 for i i to 9: count[i]=count[i-1]+count[i]
5.把桶中最优元素安装桶的顺序连接起来
6.然后从十位开始重复3开始的操作,直到最大位数都处理完





各类排序算法实现:

  1. void quicksort(vector<int>&array, int left, int right)  
  2. {  
  3.     if (left >= right)  
  4.         return;  
  5.     int pivot = array[left];  
  6.     int i = left, j = right;  
  7.     while (i < j)  
  8.     {  
  9.         while (i<j&&array[j] >= pivot)  
  10.             j--;  
  11.         if(i<j)  
  12.             array[i++] = array[j];  
  13.         while (i<j&&array[i] <= pivot)  
  14.             i++;  
  15.         if (i<j)  
  16.             array[j--] = array[i];  
  17.   
  18.     }  
  19.     array[i] = pivot;  
  20.     quicksort(array, left, i - 1);  
  21.     quicksort(array, i + 1, right);  
  22. }  
  23.   
  24. void quicksort1(vector<int>&array, int left, int right)  
  25. {  
  26.     if (left >= right)  
  27.         return;  
  28.     int m = left;  
  29.     for (int i = left + 1; i <= right; i++)  
  30.     {  
  31.         if (array[i] < array[left])  
  32.             swap(array[++m], array[i]);  
  33.     }  
  34.     swap(array[left], array[m]);  
  35.     quicksort1(array, left, m - 1);  
  36.     quicksort1(array, m + 1, right);  
  37. }  
  38.   
  39. void insertsort(vector<int>&a)  
  40. {  
  41.     int n = a.size();  
  42.     int j;  
  43.     for (int i = 1; i < n; i++)  
  44.     {  
  45.         if (a[i] < a[i - 1])  
  46.         {  
  47.             j = i - 1;  
  48.             int pos = a[i];  
  49.             for (; j >= 0; j--)  
  50.             {  
  51.                 if (pos < a[j])  
  52.                 {  
  53.                     a[j + 1] = a[j];  
  54.                 }  
  55.                 else  
  56.                     break;  
  57.             }  
  58.             a[j + 1] = pos;  
  59.         }  
  60.     }  
  61. }  
  62.   
  63. void choosesort(vector<int>&a)  
  64. {  
  65.     int n = a.size();  
  66.     int k;  
  67.     for (int i = 0; i < n-1; i++)  
  68.     {  
  69.         k = i;  
  70.         for (int j = i; j < n; j++)  
  71.         {  
  72.             if (a[j] < a[k])  
  73.             {  
  74.                 k = j;  
  75.             }  
  76.         }  
  77.         if (k != i)  
  78.             swap(a[k], a[i]);  
  79.     }  
  80. }  
  81.   
  82. void bubblesort(vector<int>&a)  
  83. {  
  84.     int n = a.size();  
  85.     for (int i = 1; i < n; i++)  
  86.     {  
  87.         bool flag = false;  
  88.         for (int j = n - 1; j >= i; j--)  
  89.         {  
  90.             if (a[j] < a[j - 1])  
  91.             {  
  92.                 swap(a[j], a[j - 1]);  
  93.                 flag = true;  
  94.             }  
  95.   
  96.         }  
  97.         if (flag == false)  
  98.             break;  
  99.           
  100.     }  
  101. }  
  102.   
  103. void shellPass(vector<int>&a,int d)  
  104. {  
  105.     int n = a.size();  
  106.     int j;  
  107.     for (int i = d; i < n; i++)  
  108.     {  
  109.         if (a[i] < a[i - d])  
  110.         {  
  111.             int pos = a[i];  
  112.             for (j = i - d; j >= 0; j -= d)  
  113.             {  
  114.                 if (pos < a[j])  
  115.                     a[j + d] = a[j];  
  116.                 else  
  117.                     break;  
  118.             }  
  119.             a[j + d] = pos;  
  120.         }  
  121.     }  
  122. }  
  123.   
  124. void shellsort(vector<int>&a)  
  125. {  
  126.     int d = a.size();  
  127.     do{  
  128.         d = d / 3 + 1;  
  129.         shellPass(a, d);  
  130.     } while (d > 1);  
  131. }  
  132.   
  133. void max_heap(vector<int>&a, int p,int len)  
  134. {  
  135.     int cur_parent = a[p];  
  136.     int child = 2 * p + 1;  
  137.     while (child < len)  
  138.     {  
  139.         if (child+1<len&&a[child] < a[child + 1])  
  140.             child++;  
  141.         if (cur_parent < a[child])  
  142.         {  
  143.             a[p] = a[child];  
  144.             p = child;  
  145.             child = 2 * p + 1;  
  146.         }  
  147.         else  
  148.             break;  
  149.     }  
  150.     a[p] = cur_parent;  
  151. }  
  152.   
  153. void heapsort(vector<int>&a)  
  154. {  
  155.     int n = a.size();  
  156.     for (int i = n / 2; i >= 0; i--)  
  157.         max_heap(a, i, n);  
  158.     for (int i = n-1; i >= 1; i--)  
  159.     {  
  160.         swap(a[0], a[i]);  
  161.         max_heap(a, 0, i);  
  162.     }  
  163.   
  164. }  
  165.   
  166. vector<int> TwoWaysMerge(vector<int>&a, vector<int>&b)  
  167. {  
  168.     vector<int>c(a.size() + b.size());  
  169.     int i = 0;  
  170.     int j = 0;  
  171.     for (int k = 0; k < a.size() + b.size(); k++)  
  172.     {  
  173.         if (i < a.size() && j < b.size())  
  174.         {  
  175.             if (a[i] < b[j])  
  176.                 c[k] = a[i++];  
  177.             else  
  178.                 c[k] = b[j++];  
  179.         }  
  180.         else if (i < a.size()&&j>=b.size())  
  181.             c[k] = a[i++];  
  182.         else if (i >= a.size() && j < b.size())  
  183.             c[k] = a[j++];  
  184.     }  
  185.     return c;  
  186. }  
  187.   
  188. void merge(vector<int>&a, int low, int m, int high)  
  189. {  
  190.     vector<int>c(high-low+1);  
  191.     int i = low;  
  192.     int j = m + 1;  
  193.     int k = 0;  
  194.     while (i <= m&&j <= high)  
  195.         c[k++] = (a[i] <= a[j]) ? a[i++] : a[j++];  
  196.     while (i <= m)  
  197.         c[k++] = a[i++];  
  198.     while (j <= high)  
  199.         c[k++] = a[j++];  
  200.     for (i = low,j=0; i <=high; i++,j++)  
  201.         a[i] = c[j];  
  202. }  
  203.   
  204. void mergesort(vector<int>&a,int left,int right)  
  205. {  
  206.     int n = a.size();  
  207.     if (right-left <= 0)  
  208.         return;  
  209.     int mid = left+(right-left) / 2;  
  210.     mergesort(a, left, mid);  
  211.     mergesort(a, mid + 1, right);  
  212.     merge(a, left, mid, right);  
  213. }  
  214.   
  215. int max_count(vector<int>&a)  
  216. {  
  217.     int maxn = a[0];  
  218.     for (int i = 1; i < a.size(); i++)  
  219.     {  
  220.         if (a[i]>maxn)  
  221.             maxn = a[i];  
  222.     }  
  223.     int count = 0;  
  224.     while (maxn)  
  225.     {  
  226.         maxn /= 10;  
  227.         count++;  
  228.     }  
  229.     return count;  
  230. }  

  231. //基数排序
  232. void redixsort(vector<int>&a)  
  233. {  
  234.     int d = max_count(a);  
  235.     vector<int>tmp(a.size());  
  236.     vector<int>count(10,0);  
  237.     int redix = 1;  
  238.     for (int i = 0; i < d; i++)  
  239.     {  
  240.         for (int j = 0; j < 10; j++)  
  241.             count[j] = 0;  
  242.         for (int j = 0; j < a.size(); j++)  
  243.         {  
  244.             int k = (a[j] / redix) % 10;  
  245.             count[k]++;  
  246.         }  
  247.         for (int j = 1; j < 10; j++)  
  248.             count[j] = count[j - 1] + count[j];  
  249.         for (int j = a.size()-1; j >=0; j--)  
  250.         {  
  251.             int k = (a[j] / redix) % 10;  
  252.             tmp[count[k] - 1] = a[j];  
  253.             count[k]--;  
  254.         }  
  255.         a = tmp;  
  256.         redix *= 10;  
  257.     }  
  258. }  



















0 0
原创粉丝点击