写在前面
之前接触了基本排序,后来老师说有比选择、冒泡、插入更厉害的排序,于是我就去研究了一下午快速排序,感觉收获还是挺多的,一种宽度比较大的排序算法。
算法讲解
思路
快速 排序是将排序的数组分成两部分,使得第一部分的所有数均小于第二部分的的数。
其中必定有一个将他们分成了两部分,为什么呢?接着看就会明白了,我们把这个可以将数组划分成两部分的数称为基准数。
现在我们得到两部分数,继续把每一部分划分成两部分,分别进行快速排序,整个排序采用递归的进行,从而达到有序的序列。
排序过程
我们要将这一组数进行排序,以最左边的一个数6为基准数,如果最左边的数小于最右边的数,那么两个数呼唤一下,想一想为什么?我们从序列的两头开始探测,干活的就是上面标红的探测器I先生和探测器J先生。最开始的时候,I先生指向最左边的数,J先生指向最后边的数。这里我们要让J先生先从右往左探测,为什么呢,慢慢你就懂了,当J先生走到比6小的数的时候就停下。接下来I先生,开始从左往右探测,探测到比6大的数就停下。
现在J先生继续一步步往左探测,他发现了4(因为4比基准数6小),于是停下,。接下来I先生继续往右走,他发现了9(比基准数6大),停下来。于是如下图:
现在J先生,继续向左探测,他发现了3(因为3比基准数6小),于是停下,这时I先生也开始往右走,结果他们撞上了!!
两个先生相遇的时候就是探测结束的时候,这时候,相遇的位置就是我们要搁置基准数的位置。
到这里,第一轮的探测就真正结束了,此时基准数6为分界点,6左边的数小于右边的数。总结一下,J先生就是要找出比6小的数,I先生就是找出比6大的数,然后交换。知道两人碰头为止。
剩下的操作就不列举了,我们将左侧和右侧分别重复上述的步骤,就可可完成排序了。
代码介绍
老师常说人生如代码,现在就把我们的想法,用代码来舞动一下。(刚接触vb的我,渴望学习更多的语言,下面介绍的代码是自己从C#中演绎过来的,同时也做了一些改动。)
'经常用到交换,写成一个过程
Sub swap(a As Integer, b As Integer)
t = a: a = b: b = t
End Sub
'快速排序过程
Sub quicksort(Left As Integer, Right As Integer)
Dim i As Integer, j As Integer, t As Integer, temp As Integer
If Left < Right Then
If a(Left) > a(Right) Then
swap a(Left), a(Right)
End If
temp = a(Left) 'temp中存放的就是基准数
i = Left
j = Right
While (i < j)
'顺序很重要,j负责的要先从右往左走
While a(j) >= temp And i < j
j = j - 1
Wend
While a(i) <= temp And i < j
i = i + 1
Wend
'交换两个数所在的位置
'当两个哨兵没有相遇时
If i < j Then
swap a(i), a(j)
End If
Wend
'将基准数归位
a(Left) = a(i)
a(i) = temp
If i > 1 Then
Call quicksort(Left, i - 1) '调用方法,处理最左边的
End If
Call quicksort(i + 1, Right)'调用方法,处理最右边的
End If
End Sub
结语
不知亲爱的小伙伴们是否发现,快速排序的交换是跳跃式的,交换的距离变大了很多了,不像冒泡排序那样是相邻的排序,这样效率就提高了很多。加油吧!