字母含义
l:left,数据最左端
r:right,数据最右端
q[ ]:存放原始数据的数组
快速排序
快速排序(quick sort)的思想是分治,将原始数据按照某一数字为标准分成两段,递归处理,对这两段内容继续按照某一数字标准细分,直到只剩下一个元素,排序结束
思路为
1、确定分界点
这里的分界点可以取q[ l ]、q[ r ]、q[ l + r >> 1 ],或随机,它是递归后排序的新端点
2、调整区间
将整个区间分为两半,分别是>=x和<=x
3、递归处理左右两段区间
方法一 数组处理
1、新开a[ ]、b[ ]
2、用i遍历q[ l ]到q[ r ],若q[ i ] <= x , x -> a[ ]; else x -> b [ ]
3、a[ ], b[ ] 依次送回q[ ]
缺点 :每次递归都需要新开a[ ], b[ ],占用空间太大
方法二 双指针处理
定义i j为 int 指针,i j分别指向q[ l ], q[ r ](涉及到while的边界问题,实操时需指向l-1和r+1), i j与q中元素比较,i需满足小于等于x,j需满足大于等于x,满足则往中间进一,不满足立即停止,两指针都停止,则交换q[ i ],q[ j ],然后继续while循环,直到i j相遇
最后按照同样的规则递归处理分好的两段,直到不可细分
quick_sort模板如下
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + r >> 1];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j);
quick_sort(q, j + 1, r);
}
归并排序
归并排序(merge sort)中,“归并”,意为归类合并,将一段数据分成两段,排好两段后进行合并,再递归处理直到只剩一个元素,程序结束
思路为
1、确定分界点mid = l + r >> 1
2、递归排序left、right
3、归并,将每段数据综合
归并排序的时间复杂度为O(nlogn),原因是每次将数据减半,这样一共处理logn次,设第k次处理,每次处理时间复杂度为O(2k*n/2k)=O(n),总和为O(nlogn)
归并排序需要辅助数组tmp[ N ],类似快排的数组做法,它用于记录归并后的数据,并将数据传回q[ ]
merge_sort模板如下
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid), merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)//只要有一个排完即停止
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];//k,i,j边走边记录,取小的值放到到临时数组中,之后对应的指针向后进一
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];//将剩余的部分补到q中
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];//辅助数组的内容传回q
}
与快速排序不同,归并排序先递归处理两边,i j 分别指向两个区间的起点,之后借助辅助数组,参照快速排序方法一的思路,对当前函数中划分好的区间进行排序,递归到区间只剩下一个函数结束,排序完成