(一)归并排序
采用分而治之的策略,即先将数组拆分,在进行排序后重组。
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;
}
};