数据结构学习之快速排序过程解析
创始人
2025-05-29 04:06:20

快速排序 Quick Sort 的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

从字面上感觉不出它的好处来。假设现在要对数组{50,10,90,30,70,40,80,60,20}进行排序。我们通过代码的讲解采学习快速排序的精妙。

// 对顺序表L做快速排序
Void QuickSort(SqList *L)
{QSort(L, 1, L->length);
}

由于需要递归调用,因此我们外封装了一个函数。

// 对顺序表L中的子序列L->r[low..high]做快速排序
Void QSort(SqList *L, int low, int high)
{int pivot;if(low < high){pivot = Partition(L, low, high);	// 将L->r[low..high]一分为二,算出枢轴值piovtQSort(L, low, pivot - 1);	// 对低子表递归排序QSort(L, pivot+1, high);	// 对高子表递归排序}
}

从这里,你应该能理解前面代码“QSort(L, 1, L->length);”中1和L->length代码的意思了,它就是当前待排序的序列最小下标值low和最大下标值high。
这一段代码的核心是“pivot=Partition(L,low,high);”在执行它之前,L.r的数组值为[50,10,90,30,70,40,80,60,20]。Partition函数要做的,就是先选取当中的一个关键字,比如选择第一个关键字50,然后想尽办法将它放到一个位置,使得它左边的值都比它小,右边的值比它大,我们将这样的关键字称为枢轴(pivot)。
在经过Partition(L,1,9)的执行之后,数组变成{20,10,40,30,50,70,80,60,90},并返回值5给pivot,数字5表明50放置在数组下标为5的位置。此时,计算机把原来的数组变成了两个位于50左和右小数组{20,10,40,30}和{70,80,60,90},而后的递归调用“QSort(L,1,5-1);"和“QSort(L,5+1,9);”语句,其实就是在对{20,10,40,30}和{70,80,60,90}分别进行同样的Partition操作,直到顺序全部正确为止。
到了这里,应该说理解起来还不算困难。下面我们就来看看快速排序最关键的Partition函数实现。

// 交换顺序表L中子表的记录,使枢轴记录到位,并返回其所在位置
// 此时在它之前(后)的记录均不大(小)于它。 
int Partition(SqList *L,int low,int high)
{int pivotkey;pivotkey=L->r[low];	/*用子表的第一个记录作枢轴记录 */while(lowwhile(low < high && L->r[high] >= pivotkey)high--;swap(L, low, high); /* 将比枢轴记录小的记录交换到低端while(low r[low] <= pivotkey)low++;swap(L, low, high); /* 将比枢轴记录大的记录交换到高端 */}return low; /*返回枢轴所在位置 */
}

1、程序开始执行,此时low = 1, high = L, length = 9。第四行,我们将L.r[low] = L.r[1] = 50赋值给枢轴变量pivotkey;
在这里插入图片描述

2、第5-13行行为while循环,目前low = 1 < high = 9,执行内部语句。
3、第七行,L.r[high] = L.r[9] = 20 > pivotkey = 50,因此不执行第8行。
4、第9行,交换L.r[low]与L.r[high]的值,使得L.r[1] = 20, L.r[9] = 50。为什么要交换,就是因为通过第7行的比较知道,L.r[high]是一个比pivotkey = 50(即L.r[low])还要小的值,因此它应该交换到50的左侧;
在这里插入图片描述

5、第10行,当L.r[low] = L.r[1] = 20,pivotkey = 50, L.r[low] < pivotkey,因此第11行,low++,此时low = 2。继续循环,L.r[2] = 10 < 50,low++,此时low = 3。L.r[3] = 90 > 50,退出循环。
6、第12行,交换L.r[low] = L.r[3] 与 L.r[high] = L.r[9]的值,使得L.r[3] = 50,L.r[9] = 90。此时相当于将一个比50大的值90交换到了50的右边。注意此时low已经指向了3,。

在这里插入图片描述
7、继续第5行,因为low = 3 < high = 9,执行循环体。

通过这段代码的模拟,大家应该能够明白, Partition 函数,其实就是将选取的pivotkey 不断交换,将比它小的换到它的左边,比它大的换到它的右边,它也在交换中不断更改自己的位置,直到完全满足这个要求为止。

相关内容

热门资讯

实测分享.“[青橙竞技]有没有... 您好:这款游戏青橙竞技可以开挂的,确实是有挂的,通过加微【4579337】咨询,很多玩家在这款游戏中...
我来教您「先锋牛牛」有没有挂!... 我来教您「先锋牛牛」有没有挂!其实是有挂亲,先锋牛牛这个游戏其实有挂的,确实是有挂的,需要了解加客服...
玩家实测“红豆斗牛透视挂下载”... 您好:红豆斗牛这款游戏可以开挂,确实是有挂的,需要软件加微信【6355786】,很多玩家在红豆斗牛这...
今日重大通报“微乐江苏麻将能不... 您好:微乐江苏麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【69174242】很多玩家在微...
重大通报“随意玩真的有挂是吗”... 您好:随意玩这款游戏可以开挂,确实是有挂的,需要软件加微信【8700483】,很多玩家在随意玩这款游...