改进版本1
舍去一边的快速排序,该边的快速排序用自身的排序代替。
def quick2(li,left,right):
while left<right:
mid=partition2(li,left,right)#索引的中间值
quick2(li,left,mid-1)#单边递归法
left=mid+1
return li
def partition2(li,left,right):
pivot=li[left]#定位左边的元素
while left<right:#还没有搜索完
# 从右边开始,将大于中间索引所在元素的元素放在左边
while left<right and pivot<li[right]:
right-=1
li[left]=li[right]#在左边加
# 从左边开始,将小于中间索引所在元素的元素放在右边
while left<right and pivot>li[left]:
left+=1
li[right]=li[left]#在右边加
li[left]=pivot#将右边的的最左端赋值为中间值
return left#返回中间值的索引
改进版本2
将有监督的快速排序优化为无监督的快速排序。
def quick3(li,left,right):
while left<right:
mid,right1 =partition3(li,left,right)#索引的中间值
quick3(li,left,right1)
left=mid
return li
def partition3(li,left,right):
pivot=li[left]#定位左边的元素
while left<=right:
while pivot<li[right]:
right-=1
while pivot>li[left]:
left+=1
if(left<=right):
li[left],li[right]=li[right],li[left]#在右边加
left += 1
right -= 1
return (left,right)#返回中间值的索引
改进版本3
在分割点选取的初始值方面进行优化,在待分割下标区间随机选取分割点下标。
def quick4(li,left,right):
while left<right:
mid,right1 =partition4(li,left,right)#索引的中间值
quick4(li,left,right1)
left=mid
return li
def partition4(li,left,right):
pivot=li[int(left+np.random.rand()%(right-left+1))]#随机取原始分割点
while left<=right:
while pivot<li[right]:
right-=1
while pivot>li[left]:
left+=1
if(left<=right):
li[left],li[right]=li[right],li[left]#在右边加
left += 1
right -= 1
return (left,right)#返回中间值的索引
改进版本4
继续在分割点选取的初始值方面进行优化,在待分割区间使用三点取中法选取初始分割点。
def quick5(li,left,right):
while left<right:
mid,right1 =partition5(li,left,right)#索引的中间值
quick5(li,left,right1)
left=mid
return li
def partition5(li,left,right):
pivot=mid_num(li,left,right)#三点取中法确定原始分割点
while left<=right:
while pivot<li[right]:
right-=1
while pivot>li[left]:
left+=1
if(left<=right):
li[left],li[right]=li[right],li[left]
left += 1
right -= 1
return (left,right)#返回中间值的索引
def mid_num(li,left,right):
a=li[left]
b=li[right]
c=li[int((left+right)/2)]
if(a>b):
a,b = b,a
if(a>c):
a,c = c,a
if (b > c):
b,c = c,b
return b