经典排序算法之快速排序

来源:互联网 发布:单身为什么不好 知乎 编辑:程序博客网 时间:2024/04/29 18:16

现在讨论一个借助“交换”实现排序的方法。主要有冒泡排序和快速排序(考虑从小到大的顺序)。

交换的意思是只在记录里面发生交换,而不借助其他的辅助空间进行存储以达到交换的目的。

一、冒泡排序

冒泡排序的过程都为大家所熟知,主要的思想是:

1)将第一个记录与第二个记录作比较,如果第一个记录的大小比第二个大,则将两个记录交换,然后比较第二个记录与第三个记录。直到第n-1个记录与第n个记录进行完比较为止,这样子记录中的最大值就“沉”到“水底”了,就成为这些记录的最后一项了;

2)重复第一步,但是此时的比较次数比第一次少一次,直到没有发生交换记录为止。

从冒泡的描述中可知,每趟排序都将记录中的最大值“下沉”,若为逆序的话,需要进行 n-1趟排序,且有n个记录,故冒泡排序的时间复杂度是O(n2)。

下面是冒泡排序的算法。

void BubleSort(SqList &L) {

i = 1;//从第一个开始比较

while(1) {

label = 0;//交换记录的标记,如果发生了交换就变为1,然后每次循环判断label是否为0,如果为0,则没有发生//交换,此时退出循环,冒泡排序结束

for(int j = 2;j < L.length;++i, ++j) {

if(L.[j] < L.[i]) {

L.[j]<->L.[r];//如果是逆序则记录发生交换

}

i = 1;//i重置为1,为下一趟排序做准备

if(label == 0) break;

}

}

二、快速排序

快速排序的发明者就是获得 1980年度图灵奖的英国牛津大学计算机科学家查尔斯.霍尔(Charles Antony Richard Hoare)。快速排序就是他在那个时候用原有的SHElLSORT(以算法的发明人D.L.Shell命令的通过调换并移动数据项实现排序的一种算法,发明于1959年)编程时分析了它的缺点而发明出来的。快速排序具有“快刀斩乱麻”的特点,能迅速地对乱序作大幅度调整,特别适合于因多次追加、删除而变得杂乱无章的数据集合。

在冒泡排序中,每趟排序都要进行n-i次比较,当遇到庞大的数据时,运行效率比较低。且在希尔排序中,每次都是缩小增量,在增量不同的情况下进行交换。快排的思想是:找到一个数,是这个数作为枢轴,使其满足位于其左边的数都比其小,位于其右边的数都比它大。这样,每趟排序就把枢轴(pivot)的位置定下来了,而且以后的每趟排序中,枢轴的位置都不会发生变化。通过一趟排序将待排记录分成独立的两部分,其中的一部分比另一部分的关键字都要小。然后分别对分割出来的几部分进行快速排序,直到整个序列有序为止。

下面是快速排序的算法实现:

void QuickSort(SqList &L) {

QSort(L, 1, L.length);

}

void QSort(SqList &L, int low, int high) {

if(low < high) {//low和high初始时分别指向表的头和尾

pivotlocation = Partion(L, low, high);//找到枢轴的位置

QSort(L, low, pivotlocation-1);//对枢轴的左边进行递归快排

QSort(L, pivotlocation+1, high);//对枢轴的右边进行递归快排

}

}

找到枢轴位置的算法实现:

int Partion(SqList L &L, int low, int high) {

L.r[0] = L.r[low];//保存枢轴的记录

pivotkey = L.r[low];//枢轴

while(low < high) {

while(low < high && L.r[high] >= pivotkey) --high;

L.r[low] = L.r[high];//比枢轴大的移到高端

while(low < high && L.r[low] <= pivotkey) --low;

L.r[high] = L.r[low];//比枢轴小的移到低端

}

L.r[low] = L.r[0];//枢轴记录到位

return low;

}

原创粉丝点击