快速排序
1.Acwing,两指针
思路:
①找分界元素 left right (left+right)/2 随机值
②调整区间,使得前指针前面的元素都>=index;后指针后面的元素都<=index
③递归左右两个区间,得到有序数组
用两个指针分别指向数组的首元素外一元素,和末元素外一元素,首先自加指向数组边界元素,分别进行比较,前指针前面的元素一定会<=index,后指针后面的元素一定>=index,最后两指针相等或者交错退出循环(如果两个指针分别指向首元素和末元素,先比较在交换两个元素的时候再加减,将会导致例如数组49 59 88 37 98 97 68 54 31 3在最后排序97 98 88时,在交换97 88 之后同时指向98,在进行判断时不满足前指针小于后指针,导致提前退出,98无法放到正确的位置上)
//错误代码
void quick_sort(int num[],int left,int right){
if(left>=right) return;
int begin=left;
int end=right;
int index=num[left];
while(begin<end){
while(num[begin]<index) begin++;
while(num[end]>index) end--;
if(begin<end){
int temp=num[begin];
num[begin]=num[end];
num[end]=temp;
}
}
quick_sort(num,left,end);
quick_sort(num,end+1,right);
}
//正确代码
#include <stdio.h>
void quick_sort(int num[],int left,int right){
if(left>=right) return;
int begin=left-1;
int end=right+1;
int index=num[left];//left---end,end+1;right----begin-1,begin;(left+right+1)/2,注意边界问题
while(begin<end){
do begin++; while(num[begin]<index);
do end--; while(num[end]>index);
if(begin<end){
int temp=num[begin];
num[begin]=num[end];
num[end]=temp;
}
}
quick_sort(num,left,end);
quick_sort(num,end+1,right);
}
/*
为什么只使用了一个end呢?(边界问题)
①同时使用end,begin
如果数组元素为1 2
第一次1不小于1,2大于1此时两个指针分别指向1,退出循环传给第二次的参数为 0,0另一个为0,1;而我们注意到0,1与第一次传入的参数是一样的,所以会发生死循环
如果end与begin交错了,无法真正的去确定要传出的参数是什么
②如果在left情况下使用begin,第一次1不小于1,2大于1此时两个指针分别指向1,退出循环传给第二次的参数为 0,0另一个为0,1;而我们注意到0,1与第一次传入的参数是一样的,所以会发生死循环
*/
2.开辟额外空间
void quick_sort(int num[].int l,int r){
if(l>=r) return;
int index=num[l];
int a[100010],b[100010];
int m=0,n=0;
for(int i=0;i<=r;i++){
if(num[i]<=index){
a[m++]=num[i];
}else{
b[n++]=num[i];
}
}
for(int i=0;i<m;i++){
num[l++]=a[i];
}
for(int i=0;i<n;i++){
num[l++]=b[i];
}
}
3.挖坑法
思路:
首先取出分界元素,留下一个坑位,从后往前查找小于Index的元素,将元素放到坑位中,此元素的位置变成一个坑位,最后必定是i==j的时候退出循环,将index放到这个位置,此时index前面的元素必定<=index,而后面的元素必定>=index
void quick_sort(int num[].int l,int r){
if(l>=r) return;
int i=l;
int j=r;
int index=num[index];//分界元素
while(i<j){
while(num[end]>=index&&i<j) end--;
//从后向前找,找到不满足条件的元素
num[begin]=num[end];
//将小于index的元素放到左侧
while(num[begin]<=index&&i<j) begin++;
//从前往后找,找到不满足条件的元素
num[end]=num[begin];
//将大于index的元素放到右侧
}
num[end]=index;
quick_sort(num,l,end-1);
quick_sort(num,begin+1,r);
}