3-5 回顾,快速二分法的疑点解惑:为啥先右j移动?因为设定a[left]为基准点
快速二分法的疑点解惑:为啥先右j移动?因为设定a[left]为基准数
思路:(查看了网上的2篇文章,关键点就是谁为基准数,我自己又尝试了不同排序,不同基准数left,right。得出👆的结论)
步骤:
1. 在序列中设a[left]为基准数。最左边设i,最右边设j(目标是从大到小排列)
2. 先从右往左找大于基准数的数,再从左往右找小于基准数的数,找到后两数交换位置
3. 然后重复2和3步骤。直到i和j最终相遇,结束本次循环。
4. 把基准数和最终相遇的数交换,结束。此步骤定位了一个数。
5. 原基准数左边和右边的序列再分别重复1-4的步骤。继续定位新的基准数。直到全部数字定位结束。
第2步,先右移动,是因为基准点设为a[left]。如果先左边i移动的话得到的a[i]必然比a[left]小。
在第4步交换a[i]和a[left]的时候导致了基准点a[left]右边竟然有比它小的数字。不符合每次循环定位1个基准点的原则,从大到小排序就失败了。(当然如果是从小往大排序也一样,会导致类似的问题出现。)
所以如果基准点定位到最左边的话,j就要先移动。当然基准点定位到最右边的话,i就先移动了。
def quicksort(a,left,right)
if left > right # 设定何时停止该方法的调用。
return
end
temp = a[left] #设定最左边的为基准数
i = left
j= right
while i != j # i和j从两边向中间靠拢,直到i和j重合,结束本轮循环。
# 根据是升序还是降序来选择 比较运算符号。
while a[j] <= temp && i < j #根据基准点是a[left],要先从右往左找。
j -= 1
end
while a[i] >= temp && i < j #再从左向右找,这里找小于基准数的数。
i += 1
end
if i < j #当i 和 j 没有相遇的时候,交换数据
t = a[i]
a[i] = a[j]
a[j] = t
end
end
a[left] = a[i] #将基准数归位。
a[i] = temp
print a.to_s + "\n" #打印每次交换的结果
quicksort(a,left,i-1) # 在quciksort的方法中,再次调用本方法,形成递归的过程。这个是处理i左边。 # 直到穷尽,即当left>right时停止调用该方法。
quicksort(a,i+1,right) # 这个处理i右边
end
a = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1]
quicksort(a,0,9)
# 0和9 代表数组最左边和最右边的key
print a
结果:
[86, 68, 42, 46, 9, 91, 77, 46, 7, 1]
[91, 86, 42, 46, 9, 68, 77, 46, 7, 1]
[91, 86, 42, 46, 9, 68, 77, 46, 7, 1]
[91, 86, 77, 46, 46, 68, 42, 9, 7, 1]
[91, 86, 77, 46, 46, 68, 42, 9, 7, 1]
[91, 86, 77, 68, 46, 46, 42, 9, 7, 1]
[91, 86, 77, 68, 46, 46, 42, 9, 7, 1]
[91, 86, 77, 68, 46, 46, 42, 9, 7, 1]
[91, 86, 77, 68, 46, 46, 42, 9, 7, 1]
[91, 86, 77, 68, 46, 46, 42, 9, 7, 1]
[91, 86, 77, 68, 46, 46, 42, 9, 7, 1] #最终结果