快速排序和归并排序

本文详细解析了快速排序和归并排序这两种经典的分治算法,包括它们的核心思想、稳定性特点、步骤演示和代码实现。快速排序通过随机选取基准进行划分,而归并排序始终取中点,两种算法各有优劣。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

快速排序

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 即未相遇且ij的左边)
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];
	}
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值