关于C++各类排序算法与std::sort性能的比较
https://blog.csdn.net/qq_24625045/article/details/49964173
堆排序
堆排序分为初始构建堆和重建堆两部分内容。
构建堆。
从顺序表构建堆,时间复杂度O(n)。每个非终端节点最多进行2次比较和互换。
重建堆。
重建堆需要取 n-1 次堆顶记录。第i次取堆顶记录重建堆,需要进行 logi 次比较和互换,耗时O(logi)(完全二叉树的某个节点到根节点的距离是 [logi]+1)。因此重建堆的时间复杂度为O(nlogn)。
总体来看,堆排序的时间复杂度为O(nlogn)。堆排序对原始记录不敏感,所以最好、最坏情况都是O(nlogn)。
#include <iostream> #include <vector> using namespace std; typedef struct { vector<int> r = {0}; int length; } SqList; void swap(SqList *L, int i, int j) { int temp = L->r[i]; L->r[i] = L->r[j]; L->r[j] = temp; } void HeapAdjust(SqList *L, int index, int len) { int temp = L->r[index]; for(int i = index*2; i <= len; i*2) { if(i < len && L->r[i] < L->r[i+1]) i++; if(temp >= L->r[i]) break; else { swap(L, index, i); index = i; } } } void HeapSort(SqList *L) { if(L ==NULL) return; int len = L->length; for(int i = (len/2); i > 0; --i) { HeapAdjust(L, i, len); } for(int j = len; j > 1; --j) { swap(L, 1, j); HeapAdjust(L, 1, j-1); } } int main (int argc, char** argv) { SqList *sl = new SqList; int m, n; cin >> n; sl->length = n; for(int i = 1; i <= n; ++i) { cin >> m; sl->r.push_back(m); } HeapSort(sl); for (int i = 0; i <= n; ++i) { cout << sl->r[i] << endl; } return 0; }
快速排序
平均时间复杂度O(nlogn);
最好情况时间复杂度O(nlogn),pivotkey基本处于顺序表中间;
最坏情况时间复杂度O(n^2),顺序表处于正序和倒序;
最好情况空间复杂度O(logn),要执行logn次递归调用;
最坏情况空间复杂度O(n),要执行n-1次递归调用;
#include <iostream> #include <vector> using namespace std; typedef struct { vector<int> r = {0}; int length; } SqList; void swap(SqList * L, int i, int j) { int temp = L->r[i]; L->r[i] = L->r[j]; L->r[j] = temp; } int getPivot(SqList *L, int low, int high) { int pivot = L->r[low]; while(low < high) { while(low < high && pivot <= L->r[high]) { high --; } swap (L, low, high); while(low < high && pivot > L->r[low]) { low ++; } swap (L, low, high); } return low; } void QSort(SqList *L, int low, int high) { if(low < high) { int pivot = getPivot(L, low, high); QSort(L, low, pivot-1); QSort(L, pivot+1, high); } } void QuickSort (SqList *L) { QSort(L, 1, L->length-1); } int main (int argc, char** argv) { SqList *sl = new SqList; int num = 0, temp = 0; cout << "cin the number of sqlist(include flag)" << endl; cin >> num; sl->length = num; for(int i = 0; i < num-1; ++i) { cin >> temp; sl->r.push_back(temp); } QuickSort(sl); for(int i = 0; i < num; ++i) cout << sl->r[i] << endl; return 0; }
对上述快速排序的改进:
1)优化选取pivotkey。采用三数取中法获取pivotkey,而不是取左边界的数。
2)优化不必要的交换。选取pivotkey后,将序列分成左右端序列,去除对pivotkey的移位操作。
3)优化小数组的排序方案。当需要排序的数组长度小于某个阈值后,采用直接插入排序。因为快速排序用到了递归操作,在大量数据排序时,这点性能影响对整体算法优势而言可以忽略不计。直接插入排序适用于小量数据的排序,最好情况下时间复杂度为O(n)。
4)优化递归操作。在下列代码中还未实施。
#include <iostream> #include <vector> #include <ctime> using namespace std; clock_t start1, end1; #define MAX_LENGTH_INSERT_SORT 7 typedef struct { vector<int> r = {0}; int length; } SqList; void swap(SqList * sq, int left, int right) { // avoid to use the swap func in Partition func. int temp = sq->r[left]; sq->r[left] = sq->r[right]; sq->r[right] = temp; } int Partition(SqList * sq, int low, int high) { int mid = 0.5*(low+high); // choose pivotkey in 3 data, low-mid-high if(sq->r[low] > sq->r[high]) swap(sq, low, high); if(sq->r[mid] > sq->r[high]) swap(sq, mid, high); if(sq->r[mid] > sq->r[low]) swap(sq, low, mid); sq->r[0] = sq->r[low]; while(low < high) { while(low < high && sq->r[0] <= sq->r[high]) high --; sq->r[low] = sq->r[high]; while(low < high && sq->r[0] >= sq->r[low]) low ++; sq->r[high] = sq->r[low]; } sq->r[low] = sq->r[0]; return low; } void InsertSort(SqList * sq, int low, int high) { int temp; for(int i = low+1; i <= high; ++i) { if( sq->r[i] < sq->r[i-1] ) { temp = sq->r[i]; int j; for(j = i-1; (sq->r[j] > temp) && (j>=low); --j ) { sq->r[j+1] = sq->r[j]; } sq->r[j+1] = temp; } } } void Sort(SqList * sq, int low, int high) { int pivotkey; if( (high-low) > MAX_LENGTH_INSERT_SORT ) { pivotkey = Partition(sq, low, high); Sort(sq, low, pivotkey-1); Sort(sq, pivotkey+1, high); } else // length is too small, use insert sort InsertSort(sq, low, high); } void QuickSort(SqList * sq) { Sort(sq, 1, sq->length); } int main (int argc, char** argv) { SqList *sl = new SqList; int num = 0, temp = 0; cout << "cin the number of SqList" << endl; cin >> num; sl->length = num; for(int i = 0; i < num; ++i) { cin >> temp; sl->r.push_back(temp); } start1 = clock(); QuickSort(sl); end1 = clock(); cout << "cost time = " << (double)(end1 - start1) / CLOCKS_PER_SEC << endl; cout << "*************" << endl; for(int i = 1; i <= num; ++i) cout << sl->r[i] << endl; return 0; }