(四)简单介绍快速排序

本次要介绍快速排序,不稳定排序中最快的一种了。

快排核心理念

找到一个基准数(一般设在队首),并在队首,队尾各设置一个“小人儿”。先让右面的小人儿一步步往左边走。我们现在要确保的就是小人儿所经过的数字都要大于等于基准数。如果数字小于基准数,就让小人儿先停一下,让左面的小人儿走。左面的小人儿依葫芦画瓢,只是反一下而已。直到两个小人都停下了,互换他们的数。如此重复多次,小人儿会在一个地方碰头,此时左面的数(除基准数)都小于基准数,右面的数都大于基准数。这时互换“碰头数”和基准数,左右就各生成了新的两组数,重复前面的步骤就好。直到队首位置已经大于队尾位置。
时间复杂度为 O ( n ∗ l o g O(n*log O(nlog n ) n) n),最糟为 O ( n 2 ) O(n^2) O(n2)

一步步展现快排是如何工作的

实现快排要用递归。先写出框架:

int numlist[15];
void quicksort(int head,int tail){

}

很明显,参数 h e a d head head t a i l tail tail是数组的第一个位置和最后一个位置
为什么我们要写出参数 h e a d head head t a i l tail tail呢?因为我们在排序时经常会有在数组的指定区域内进行排序这种情况。这时 h e a d head head t a i l tail tail就派上用场了。

写递归要先写出终止条件(本例是队首位置已经大于队尾位置)哦。

if(head>tail)
	return;

在数组里找一个基准数,我们一般选择第一个数
然后我们创建 i i i j j j作为两个小人。

int st=numlist[1];
int i=head,j=tail;

小人的移动可能要循环多次,直到碰头,所以这么写:

while(i!=j){

}

之后从表示 j j j小人逐渐往前移动。靠后的位置应该比基准数大。如果它比基准数小了,我们停下。

while(numlist[j]>=st&&i!=j){
	j--;
}

i i i也同理往后移动。

while(numlist[i]<=st&&i!=j){ 
	i++;
}

现在 i i i j j j都停下了,我们互换

numlist[i]+=numlist[j];
numlist[j]=numlist[i]-numlist[j];
numlist[i]-=numlist[j];

不熟悉这种方法的在这里普及一下,互换 a a a b b b这样做:
a = a + b a=a+b a=a+b
b = a − b ( = a + b − b = a ) b=a-b(=a+b-b=a) b=ab(=a+bb=a)
a = a − b ( = a + b − a = b ) a=a-b(=a+b-a=b) a=ab(=a+ba=b)

现在 i i i j j j已经碰头了,我们把它和基准数互换(基准数的位置其实就是 h e a d head head)。
由于 i i i j j j碰头了,所以它们是一样的,用哪个都可以。

numlist[head]+=numlist[i];
numlist[i]=numlist[head]-numlist[i];
numlist[head]-=numlist[i];

最后写递归的回调,处理前半部分和后半部分:

quicksort(head,i-1);
quicksort(i+1,tail);

示例代码

int numlist[15]; 
void quicksort(int head,int tail){ 
	if(head>tail) 
		return; 
	int st=numlist[1]; 
	int i=head,j=tail;
	while(i!=j){
		while(numlist[j]>=st&&i!=j){
			j--;
		}
		while(numlist[i]<=st&&i!=j){
			i++;
		}
		numlist[i]+=numlist[j];
		numlist[j]=numlist[i]-numlist[j];
		numlist[i]-=numlist[j];
	}
	numlist[head]+=numlist[i];
	numlist[i]=numlist[head]-numlist[i];
	numlist[head]-=numlist[i];
	quicksort(head,i-1);
	quicksort(i+1,tail);
}

使用STL标准模板库

S T L STL STL为我们封装好了很多常用算法,后面我们还有遇到它。本次我们先介绍第一个 S T L STL STL函数: s o r t sort sort函数
s o r t sort sort函数内部是用快排来实现的,我们先介绍它所需要的头文件

#include 

它的使用方法是

sort(head pointer,tail pointer,sort method);

这里告诉大家, t a i l tail tail p o i n t e r pointer pointer应该设置为最后一位要排序的地址的下一地址。
如何获取数组中的地址呢?其实数组的名称就是数组的首地址了。例:
a a a = = = a [ 0 ] a[0] a[0]的地址
a + 2 a+2 a+2 = = = a [ 2 ] a[2] a[2]的地址
a + 8 − 3 a+8-3 a+83 = = = a [ 5 ] a[5] a[5]的地址
如果是从小到大排序,则不用写 s o r t sort sort m e t h o d method method。如果从大到小,那么这样写:

bool compare(int a,int b){
	return a>b;
}
sort(head pointer,tail pointer,compare);

由于是从大到小,所以就这样写。当然,你自己也可以润色 c o m p a r e compare compare函数啦。

你可能感兴趣的:(算法,算法)