您的位置:首页 > 其它

快速排序-总结与改进

2017-03-23 12:04 197 查看
之前的几次面试都有问到快速排序,我的写法都是按照算法导论上随便写写的:

一:基本快速排序:(参照算法导论)

#快速排序
def quicksort(nums,p,r):
if p<r:
q=partition(nums,p,r)
quicksort(nums,p,q-1)
quicksort(nums,q+1,r)
return

def partition(nums,p,r):
x=nums[r]
i=p-1  #记录位置
for j in range(p,r):
if nums[j]<=x:
i+=1
nums[i],nums[j]=nums[j],nums[i]
nums[i+1], nums[r] = nums[r], nums[i+1]
return i+1


二:偶尔会问怎么改成非递归的

def quicksort2(nums,p,r):
#非递归实现,只需要申请一个 栈来记录 需要排序的起始位置与终点位置
stack=[p,r]
while stack:
new_r=stack.pop()
new_p=stack.pop()
q=partition(nums,new_p,new_r)
if new_p<q-1:
stack.extend([new_p,q-1])
if new_r>q+1:
stack.extend([q+1,new_r])
return nums


三:写成一个函数

def quicksort(nums,p,r):
if p>=r:return
x=nums[r]
i=p-1  #记录位置
for j in range(p,r):
if nums[j]<=x:
i+=1
nums[i],nums[j]=nums[j],nums[i]
nums[i+1], nums[r] = nums[r], nums[i+1]
q=i+1
quicksort(nums,p,q-1)
quicksort(nums,q+1,r)
return


四:如果从前端取值:

def quicksort(nums,p,r):
if p>=r:return
x=nums[p]
i=p  #记录位置
for j in range(p+1,r+1):
if nums[j]<x:
i+=1
nums[i],nums[j]=nums[j],nums[i]
#最后的结果:nums[p+1,,,,i-1]都小于x;nums[i,...,r]>=x
nums[i], nums[p] = nums[p], nums[i]
quicksort(nums,p,i-1)
quicksort(nums,i+1,r)
return


五:改进一:

考虑极端的情况:如果n个数都相同,插入排序是O(n),而快排则变成了平方级别的。

考虑从两端划分:

i从左往右扫,j从右往左扫;

如果i>=j循环终止

否则交换i,j对应的值(这里相当于又找到了一个大于等于key和一个小于等于key的数,i++,j–)

(python没有do while 写成这个会比较简单)

def quicksort(nums,p,r):
if p>=r:
return
key=nums[p]
i=p+1  #从左往右
j=r #从右往左
while True:
while i<=r and nums[i]<key:
i+=1
while nums[j]>key:
j-=1
if i>=j:
break
#此时nums[p+1,,,i-1]都小,注意i可能为r+1
#nums[j+1,r]都大
nums[i],nums[j]=nums[j],nums[i]
i+=1
j-=1
nums[p],nums[j]=nums[j],nums[p]
quicksort(nums,p,i-1)
quicksort(nums,j+1,r)
return


六:改进二:

如果对于排序好的数,选取第一个元素做划分会导致效率的降低(平方级别)。

所以应该选择随机选择划分元素.

在 if的后面加上:

x=random.randint(p,r)
nums[x],nums[p]=nums[p],nums[x]


七:改进三:

修改 if

快速排序花费了大量的时间来排序很小的子数组,如果采用插入排序会更快

可以修改为:

if p-r<cutoff:
return


其中,cutoff是一个小整数,然后选择其他排序算法进行排序。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  快速排序 算法