快速排序
快速排序是每次选一个基准,找到基准的正确位置,一般选择第一个数为基准。
如 2 4 6 4 3 1 1 6
选2为基准base找到2的正确位置,即2在排序完成的位置,2前边的比2小,2后边的比2大。
1 1 2 4 6 4 3 6
然后将2前边的再次排序,后边的再次排序。直到完全排序完成。
程序的主要思想:设置两个指针一个pre保存小于base的最后一位,一个是cur当前指针。当前数大于base时,当前指针加1,扩充大于的区间,当小于base时,将pre加1,此时pre指向的时大于区间的第一个值,与当前值cur交换,此时cur指向的就是大于区间,cur加1。
a = [6, 3, 7, 2, 8, 5, 3, 4,9,4,5,6,7,3,11,33,66,8,66]
def quck(arr,l,r):
base = arr[l]
cur=l+1
pre = l
while cur < r:
if arr[cur] > base:
cur+=1
else:
pre+=1
arr[pre], arr[cur] = arr[cur], arr[pre]
cur+=1
arr[l],arr[pre]=arr[pre],arr[l]
return pre
def QuickSort(arr,l,r):
if l >=r:
return
mid= quck(arr,l,r)
# print(mid,arr[l:mid],arr[mid+1:r])
QuickSort(arr,l,mid)
QuickSort(arr,mid+1,r)
return arr
print(QuickSort(a,0,len(a)))
改进一:当数组是相对有序的时候选取第一位为base的话导致快速排序退化为o(n^2),所以可以随机初始化base修改代码如下:
def quck(arr,l,r):
s = int(random.uniform(l, r - 1) + 0.5)
arr[s],arr[l]=arr[l],arr[s]
base = arr[l]
cur=l+1
pre = l
while cur < r:
if arr[cur] > base:
cur+=1
else:
pre+=1
arr[pre], arr[cur] = arr[cur], arr[pre]
cur+=1
arr[l],arr[pre]=arr[pre],arr[l]
return pre
改进二:当数组中有大量重复元素导致样本失衡两边不均匀,可以使用两个指针,将大于和小于的区域方两头。
def quck(arr,l,r):
s = int(random.uniform(l, r - 1) + 0.5)
arr[s],arr[l]=arr[l],arr[s]
base = arr[l]
i=l+1
j = r-1
while True:
while i<=r-1 and arr[i] <= base:
i+=1
while j >=l+1 and arr[j] >= base:
j -= 1
if i>j: break
arr[i],arr[j]=arr[j],arr[i]
i+=1
j-=1
arr[l], arr[j] = arr[j], arr[l]
return j