基础算法——快速排序和归并排序 目录
快速排序
1.知识点
1.快速排序主要思想基于分治
2.快速排序不稳定
例如 3 1 2 3 5
,分界点 x=3
当i指向第一个数3
,j指向倒数第二个数3
,会停下来交换两个数
2.步骤
1.确定分界点x
q[l]
、q[(l+r)/2]
、q[r]
、随机
2.调整区间
区间划分成两部分,使得满足条件:
1、左区间里的所有的数都 <=x
2、右区间里的所有的数都 >=x
比如这个数 ==x
,它在左边和右边都是可以的
实现操作:
两个指针i、j
分别指向头和尾
从i开始交替移动i、j
移动i直到指向的数满足>=x
,说明这个数属于右半边,则停下来
去移动j,直到j指向的数满足 <=x
,说明这个数属于左半边,则停下来
交换这两个数(前提条件是i<j
即未相遇且i
在j
的左边)
i,j
继续往中间走直至相遇
3.递归
递归处理左右两段
3.代码(带注释)
void quick_sort(int q[],int l,int r){
if(l>=r){ // 区间没有数或者只有一个数则无需排序
return;
}
int x=q[(l+r)/2]; //确定分界点
/**
每一次交换完之后要向中间移动一格
所以每一次先把两个指针往中间移动一次,再判断
所以一开始需要放到两个边界点的外面一格,这样经过移动一格后会指导真正的边界
**/
int i=l-1;
int j=r+1;
while(i<j){ // 还未相遇
while(q[++i]<x); // 说明不满足右区间的条件即不满足 >=x
while(q[--j]>x); // 说明不满足左区间的条件即不满足 <=x
if(i<j){ // 可能i已经在j的右边了才停下来,此时无需交换位置
swap(q[i],q[j]);
}
}
quick_sort(q,l,j); // 递归左区间
quick_sort(q,j+1,r); // 递归右区间
}
4.代码(不带注释)
void quick_sort(int q[],int l,int r){
if(l>=r){
return;
}
int x=q[(l+r)/2];
int i=l-1;
int j=r+1;
while(i<j){
while(q[++i]<x);
while(q[--j]>x);
if(i<j){
swap(q[i],q[j]);
}
}
quick_sort(q,l,j);
quick_sort(q,j+1,r);
}
归并排序
1.知识点
1.主要思想是分治
2.归并排序是稳定的
3.与快速排序不同的是:
快速排序以数组中任意一个数为分界点,归并排序以整个数的中间为分界点
快速排序先排序再递归两边,而归并排序是先递归排序
2.步骤
1.确定分界点
mid=(l+r)/2
2.递归排序左边和右边
3.归并
合二为一,把两个有序的数组合并成一个有序的数组
实现操作:
1.有两个有序序列后,一个指针指向第一个序列的第一个数即最小值,另一个指针指向第二个序列的第一个数即最小值
2.每次判断两个指针指向的数字哪个更小,将其存入答案数组,并将这个指针向后移动一位,直到其中有一个指针到序列的最后
3.将剩下的序列的那一段直接补到答案序列中
3.代码(带注释)
int temp[N]; // 用来存答案的临时数组
void merege_sort(int q[],int l,int r){
if(l>=r){ // 区间没有数或者只有一个数则无需排序
return;
}
int mid=l+r >> 1; // 数组的中间点为分界点
merege_sort(q,l,mid); // 递归左半边
merege_sort(q,mid+1,r); // 递归右半边
int k=0; //k用来记录temp数组存储到第几个了
int i=l; //i用来表示指向第一个有序序列的第一个数即最小值
int j=mid+1; //j用来表示指向第二个有序序列的第一个数即最小值
while(i<=mid && j<=r){ // 当两个指针都指向所在序列的范围时
if(q[i]<=q[j]){ // 比较两个指针所指向的数,选择小的那个数存入temp[],并向右移动一格指针
temp[k++]=q[i++];
}
else{
temp[k++]=q[j++];
}
}
while(i<=mid){ // i指针还没有到终点,将剩余的数直接存入temp[]
temp[k++]=q[i++];
}
while(j<=r){ // j指针还没有到终点,将剩余的数直接存入temp[]
temp[k++]=q[j++];
}
for(int i=l,j=0;i<=r;i++,j++){ //将temp数组的数据存回到q[]
q[i]=temp[j];
}
}
4.代码(不带注释)
int temp[N];
void merege_sort(int q[],int l,int r){
if(l>=r){
return;
}
int mid=l+r >> 1;
merege_sort(q,l,mid);
merege_sort(q,mid+1,r);
int k=0;
int i=l;
int j=mid+1;
while(i<=mid && j<=r){
if(q[i]<=q[j]){
temp[k++]=q[i++];
}
else{
temp[k++]=q[j++];
}
}
while(i<=mid){
temp[k++]=q[i++];
}
while(j<=r){
temp[k++]=q[j++];
}
for(int i=l,j=0;i<=r;i++,j++){
q[i]=temp[j];
}
}