快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
比如一个无序的序列a[7]:
4 6 8 9 3 1 5
l:0 r:6
现在我们要对它做降序排列
1. 定义两个位置标记l和r在要排序部分的左右两边,(这里是0号和6号), 先选定第一个元素4作为一个比较的基准值,
2.然后从右往左找一个大于4的数,这里是5。然后把右标记指向5也就是a[6],(其实原来的j就标记了这)。这时我们把r和l标记的两个数a[r]和a[l]交换。交换完成后,就变成了这样:
5 6 8 9 3 1 4
l:0 r:6
3. 然后从左到右找一个小于4的数,这里是3。然后让左标记指向它,然后交换a[l]与a[r]。交换完成后,就变成了这样:
5 6 8 9 4 1 3
l:4 r:6
然后重复第2步,让 r 从现在的位置向左移动找到一个大于4的数,这时我们发现l和r相遇了,这样我们就得到了一个特殊的数组----以元素4为界,它左边的数总是大于4的,它右边的数总是小于4的。这时我们把数组取出2份,左边一份是所有大于4的数,是a[0]~a[3]。然后右边一份是所有小于4的数,a[5]~a[6]。
然后我们分别让这两个子序列进行上面的操作:
对于左边部分a[0]~a[3]:5 6 8 9
选定左边第一个数a[0],也就是5为基准值,然后让所有比5大的数都在5左边,让所有比5小的数都在5右边。
得到:6 8 9 5
然后再继续分,递归地执行这个过程(让所有比基准值大的数都在基准值左边,所有比基准值小的数都在基准值右边),然后直到不能再分了。
这时我们就能得到一个降序的序列。
具体实现如下:
//LR表示要排序部分的左右边界,如果要排序一个10个元素的数组,就调用QuickSort(0,10);
void QuickSort(int L, int R)
{
//设置两下标,分别为要排序部分的开始和结束元素的数组下标
int l = L, r = R - 1;
if (l >= r) return;
int key = a[L]; //以序列第一个元素为基准
while (l < r)
{
//让右边的下标r从右往左找到第一个小于key的数
while (a[r] <= key&&r>l) r--;//从右往左找到一个比key大的值
swap(&a[r], &a[l]); //交换左右两个下标位置的值
if (l == r)break; //如果l等于r,就结束循环
//让左边的下标l从左往右找到第一个大于key的数
while (a[l] >= key&&r>l)l++;//从左往右找到一个比key小的值
swap(&a[r], &a[l]); //交换左右两个下标位置的值
if (l == r)break; //如果l等于r,就结束循环
}
//上面的部分已经让r==l,
//并且所有比key小的数都在key的左边,所有比key大的数都在key右边
QuickSort(L, r);
QuickSort(r+1, R);
}
上面代码是实现降序的,如果想实现升序,只要把两个while里面的>=和<=互换。
这里有一个例子,随机生成50000个数,然后降序输出
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define N 50000
int a[N];
void init()//初始化数组
{
srand((unsigned)time(NULL));
for (int i = 0; i < N; i++)
{
a[i] = rand();
}
}
void print() //输出数组元素
{
int i;
for (i = 0; i < N;i++)
printf("%d ",a[i]);
printf("\\n");
}
void swap(int*a, int*b)//交换两个变量的值
{
int c = *a;
*a = *b;
*b = c;
}
//LR表示要排序部分的左右边界,如果要排序一个10个元素的数组,就调用QuickSort(0,10);
void QuickSort(int L, int R)
{
//设置两下标,分别为要排序部分的开始和结束元素的数组下标
int l = L, r = R - 1;
if (l >= r) return;
int key = a[L]; //以数组第一个元素为基准
while (l < r)
{
//让右边的下标r从右往左找到第一个小于key的数
while (a[r] <= key&&r>l) r--;
swap(&a[r], &a[l]); //交换左右两个下标位置的值
if (l == r)break; //如果l等于r,就结束循环
//让左边的下标l从左往右找到第一个大于key的数
while (a[l] >= key&&r>l)l++;
swap(&a[r], &a[l]); //交换左右两个下标位置的值
if (l == r)break; //如果l等于r,就结束循环
}
//上面的部分已经让r==l,
//并且所有比key小的数都在key的左边,所有比key大的数都在key右边
QuickSort(L, r);
QuickSort(r+1, R);
}
int main()
{
init();
printf("数组原来是这样的:\\n");
print();
QuickSort(0,N);
printf("\\n排序后:\\n");
print();
system("pause");
}
- 本文链接: http://hjwblog.com/archives/快速排序
- 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!