【notes】排序

我对于四种排序的理解

1.冒泡排序 (Bubble Sort)

代码如下:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n=10,a[10]={9,8,0,6,3,1,4,7,5,2};
	for(int i=0;i<n-1;i++)
	for(int j=0;j<n-i-1;j++)
	if(a[j]>a[j+1])swap(a[j+1],a[j]);
	for(int k=0;k<n;k++)cout<<a[k]<<" ";
} 

冒泡排序有n个数据时,程序需要排(n-1)遍,即i从0到n-1的过程。每排一遍,数组中最大的数就会被交换到数组的后面(具体是第n-i-1位),每次i循环的结束后排出的数字就已经排在了正确的位置。
并且随着i的变大,参与排序的数组长度越来越短。可以形象地理解为数组在”从右到左缩短“。

2.选择排序(Selection Sort)

代码如下:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n=10,a[10]={9,1,5,4,6,3,2,0,7,8};
	for(int i=0;i<n-1;i++){
		int p=i;
		for(int j=i+1;j<n;j++)if(a[j]<a[p])p=j;
		if(p!=i)swap(a[i],a[p]);
	}
	for(int j=0;j<n;j++)cout<<a[j]<<" ";
} 

相对于冒泡排序,选择排序的交换次数大大减小,因为选择的每一次i循环是找出最值的下标,在找到后直接和左端的值交换。
和冒泡一样,每一次排序之后数组中的最值会被排到数组的一端。稍稍不同的是这段选择排序相交于冒泡的“从右到左缩短”,他是“从左到右缩短”的。

==>观察冒泡排序和选择排序,可以发现在整个过程中数组的需要排序的有效长度在单方向变短。

3.插入排序(Insertion Sort)

代码如下:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int x=0,t,a[10]={9,8,0,6,3,1,4,7,5,2};
	const int n=10;
	for(int i=1;i<n;i++){
		x=a[i];
		int j=i-1;
		while(j>=0&&x<a[j])a[j+1]=a[j--];
		a[j+1]=x;
		/*对a[j+1]的解释:
			因为不论while中的条件满不满足,j都会自减,
		  	所以应该得到的位置找要加一*/
	}
	for(int j=0;j<n;j++)cout<<a[j]<<" ";cout<<endl;
} 

插入排序是先将第一个数字看成有序数组,再拿第二个数来比较,比他小放前面,比他大放后面。和冒泡类似,插入排序的未排序数组也在“从左向右缩短”。
但是这种算法在找到应该插入的位置时要把该位置以及之后所有已经排好序的数字后移一个位置,交换次数比较多。

=>这三种排序方法有一个共同的特点:未排序的数组长度是单向缩短的

4.快排(Quick Sort)

快排根据我的了解是有多种写法的,我掌握的比较好的是“挖坑法”。

void qs(int a[],int l,int r){
	int i=l,j=r,
			x=a[l];//把a[l]挖出来放到x变量里,形成一个“坑”
	while(i<j){
		while(i<j&&a[j]>=x)j--;//找到右边比x大的位置
		if(i<j){
			a[i++]=a[j];//放到刚刚的“坑”里
		}
		while(i<j&&a[i]<x)i++;
		if(i<j){
			a[j--]=a[i];
		}
		//for(int k=0;k<n;k++)cout<<a[k]<<" ";cout<<endl;
	}
	a[i]=x;//将x归位
	if(i<r)qs(a,i+1,r);
	if(l<i)qs(a,l,i-1);
}

和之前的排序方法不同的是,快排每一个大while都是把基准数x(基准数可以任意取)排到了它应该在的位置,而不是像前几种方法一直在扩大已经排序的数据长度。
快排将原来的数列变换成“A_x_B”的结构(A里所有数不大于x,B里所有数不小于x)

值得注意的点有:
1…大while结束后,i==j,且i就是x的正确位置。
2…每一次“填坑”之后要i++/j–
3…进入递归时,要注意将排好的x“挖空”,A部分的范围是[l,i-1],B部分的范围是[i+1,r]。

排序还有很多很多种,慢慢学咯~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值