(一)归并排序
采用分而治之的策略,即先将数组拆分,在进行排序后重组。
C++代码如下:
Class MergeSort { public: int* mergeSort(int* A, int n) { int left = 0, right = n-1; ArraySort(A, left, right); return A; } void ArraySort(int* A, int left, int right) //数组拆分 { if(left<right) { int mid = left + (right-left)/2; // mid = (right+left)/2这种方法不是很推荐,因为可能超内存范围 ArraySort(A, left, mid); ArraySort(A, mid+1, right); if(A[mid]>A[mid+1]) ArrayMerge(A, left, mid, right); } } void ArrayMerge(int* A, int left, int mid, int right) //数组合并 { int temp[right-left+1]; int i = left, j = mid+1, k = 0; while(i<=mid && j<=right) { if(A[i]<A[j]) temp[k++] = A[i++]; else temp[k++] = A[j++]; } while(i<=mid) temp[k++] = A[i++]; while(j<=right) temp[k++] = A[j++]; for(i=0; i<k; ++i) A[left+i] = temp[i]; } };
(二)快速排序
随机选取一个数做基准,数组中小于该基准的数放在基准的前面,大于该基准的放在后面。
C++代码如下:
class QuickSort { public: int* quickSort(int* A, int n) { qSort(A, 0, n-1); return A; } void qSort(int* A, int left, int right) { if(left < right) { int par = Partition(A, left, right); qSort(A, left, par-1); qSort(A, par+1, right); } } int Partition(int* A, int left, int right){ int j = left-1, m = A[right]; for(int i=left; i<right; i++) { if(A[i]<=m) { j++; if(i!=j) swap(A[j], A[i]); } } swap(A[right], A[j+1]); return j+1; } };
(三)堆排序
利用二叉树结构的性质,可构造大(小)顶堆。
大(小)顶堆:每个父节点值均大于等于(小于等于)左右孩子节点的值, A[i]>=A[2i+1] && A[i]>=A[2i+2];
常用于取前N个最大(小)值。
大顶堆的基本思想:
1. 将初始待排序列A[0,...n-1]构建大顶堆
2. 将堆顶元素A[0]与A[n-1]交换,得到无序序列A[0,..,n-2]和有序序列A[n-1],调整序列为大顶堆
3. 重复步骤2,直到有序元素个数为n-1
class HeapSort { public: int* heapSort(int* A, int n) { // write code here for(int i = n/2-1; i>=0; i--) //建立大顶堆,从最底层的父节点开始 heapAdjust(A, i, n); for(int i = n-1; i>=0; i--) { swap(A[i], A[0]); heapAdjust(A, 0, i); } return A; } void heapAdjust(int* A, int p, int len) { int curParent = A[p]; int child = 2*p + 1; while(child < len) { if(child+1<len && A[child]<A[child+1]) child++; if(A[child] > curParent) { A[p] = A[child]; //如果其孩子中有大的,会上移,curParent还要继续下移。 p = child; child = 2*p + 1; } else break; } A[p] = curParent; } };
参考:https://segmentfault.com/a/1190000002466215
(四)希尔排序
插入排序的改进版,与插入排序的不同之处为,可逐渐减小步长进行数据对比较,直至步长为1。相较于插入排序,效率更高。
class ShellSort { public: int* shellSort(int* A, int n) { for(int gap = n/2; gap>0; gap /= 2) { for(int i=0; i < gap; i++) { for(int j=i+gap; j<n; j+=gap) if(A[j-gap]>A[j]) { int temp = A[j]; int k = j-gap; while(k>=0 && A[k]>temp){ A[k+gap] = A[k]; k = k-gap; } A[k+gap] = temp; } } } return A; } };