快速排序算法,看看名字就知道它在所有的目前已知的算法是最快的,它的基本思想是“分治”,其实算法不难理解,看看代码也能明白什么意思,大一上学期就学会了这种算法,可是每次过了老长时间,就把它给忘了,最终还是要看模版。因此代码无所谓,关键是你必须理解这种思想,不是明白就行!!好吧废话多了~
C++STL模板库<algorithm>和C语言函数库<stdlib.h>都有对应的实现,我就不介绍了~但给出相应的库函数链接:
C qsort(): http://www.cplusplus.com/reference/cstdlib/qsort/?kw=qsort;
C++ sort(): http://www.cplusplus.com/reference/algorithm/sort/?kw=sort;
现在开始详细的讲解一下快速排序,分治的思想你懂么?给你1000个数,让你从小到大排序,直接排序肯定很困难,因此,如果我们从1000个数中随机选出一个数pivot,所有的数都和pivot比较,然后把所有的比pivot小的数放到pivot的左边,所有比pivot大的放到pivot的右边,这样最终我们就找了pivot的最终的位置 如下图所示
<pivot | pivot | >=pivot |
那么,如何才能找到pivot的最终位置呢?一般情况下,我们选择pivot的值为要排序数组的的第一个元素或者是最后一个元素,事实上任何一个元素都可以,然后就是确定pivot在数组中正确的位置,以后都不会对其进行改动。下面说一下一种实现,我们需要一个整数索引(数组的下标)loc,loc的位置左边都是小于pivot的,loc的右边都是大于pivot的,初始化的时候 loc指向待排序序列的第一个元素。然后遍历整个序列(i = start ,i<end),如果比pivot小,就要求这个数和loc所指向的数进行交换,然后loc++,这样loc左边的肯定小于pivot。然后一次遍历之后loc的位置就是pivot的最终位置,把pivot所在位置的元素与loc指向的那个元素进行交换。然后递归~~分治 。
C++代码如下:排序元素区间[start,end)
void quick_sort(int arr[],int start,int end)
{
if(start >= end)
return;
int loc = start;
int tmp;
for(int i = start;i < end;++i)
{
if(arr[i] < arr[end-1])
{
tmp = arr[i];
arr[i] = arr[loc];
arr[loc] = tmp;
loc++;
}
}
tmp = arr[end-1];
arr[end-1] = arr[loc];
arr[loc] = tmp;
quick_sort(arr,start,loc);
quick_sort(arr,loc+1,end);
}
我感觉这个是最简洁的快速排序算法,利用loc需找pivot的合适位置。。额,我这里的pivot是arr[end-1]~
这里还有一种实现快速排序的实现形式,我简要说一下它的实现的这种技巧。关键还是要找到pivot的正确的位置,pivot可以任选~,但是一般选择待排列的第一个元素,并且对于下面的快排你最好用首元素作为基准!如果两边找速度是不是更快呢?这里需要两个整数索引i,j 。i的左边(不包括i)是小于pivot的,j的右边肯定是大于pivot的,i初始化为start-1,j初始化为end,然后压缩区间[i,j]因为这个区间的元素与pivot的关系是不确定的,首先左边i开始i++遇到大于pivot的元素就停止,然后j--遇到第一个小于pivot的元素就停止,然后如果i<j,就把i,j所指向的元素进行交换,交换后i所指向的那个元素就小于pivot了j所指向的元素就大于pivot了,如果i>=j就退出循环,j的位置就是pivot的位置。把pivot放到j这个位置就行了~,至于为什么是j不是i下图可以说明:
假设某次交换后结果如下,明显i<j
45 | 43 | 34 | 47 | 72 | 100 | 49 | 80 |
i j
然后我们i++ 直到i所指向的元素大于pivot,我们得到
45 | 43 | 34 | 47 | 72 | 100 | 49 | 80 |
i
j
然后j--直到j所指向的元素小于pivot,我们得到
45 | 43 | 34 | 47 | 72 | 100 | 49 | 80 |
j i
这个时候因为j<=i了因此要退出循环 如果i指向的元素和基准交换(也就是45和47交换~~很明显错了,因为这个基准要和比它小的交换,而不是比它大的)
C++代码如下
void quick_sort(int a[],int start,int end)
{
if(start >= end) return;
int i = start;
int j = end;
int pivot = a[start];
int tmp;
while(true)
{
do {
i++;
}while(a[i] < pivot);
do {
j--;
}while(a[j] > pivot);
if(i >= j)
{
break;
}
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
tmp = a[start];
a[start] = a[j];
a[j] = tmp;
quick_sort(a,start,j);
quick_sort(a,j+1,end);
}