快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
快速排序的重点在于用O(n)的时间复杂度把数组分为左右俩部分,一部分大,一部分小,他们之间的分界是一开始取的分界值。
我们先定义一个数组int a[] = {93,27,30,2,8,12,2,8,30,89};我们取a[0]作为分界值,然后设置两个变量,一个从数组最左边开始,另一个从数组最右边开始。我们先从右向左扫描,如果发现元素比分界值小,就进行交换,把小的元素扔到左边过去,这样子第一次交换分界值a[0]就换到了右边的位置,这时候我们就应该从左往右扫描了,因为这时候分界值的右边以及排序好了,都是比分界值大的元素,然后再从右往左扫描,如此循环往复,直到这两个变量指针相遇为止。
这里有一个需要我们注意的点,如果我们把a[0]作为分界值,那么我们的第一次扫描应该从右往左,因为这时候分界值的左边是默认都比a[0]小的。
从另一个角度理解,我们其实也不一定要取数组的第一个元素或者最后一个元素作为分界值,我们可以随便取中间的一个元素作为分界值,然后可以先从右边扫描,把小的元素都扔到数组左边,然后再从数组左边扫描,把大的元素放到分界值的右边。但是这会造成一个问题,就是我们在第二次扫描的时候需要对分界值的位置进行移动,其他数组元素的位置也跟着移动,这样的时间复杂度就大了,这样的代价是我们不能接受的。但是如果我们快速排序的不是数组,而是链表里面的元素,就没有这个问题了。
所以,使用快速排序,如果是对于数组的话,我们的分界符只能取数组的第一个元素或者最后一个元素。但是如果我们是对链表进行快速排序的话,那么我们就无所谓取哪一个元素作为分界符了。