使用Python实现的4种快速排序算法

  快速排序算法,总体来说就是选一个基准值,把小于基准值的分一拨,把大于基准值的分到另一拨,然后递归。

  有区别的是,分区算法有差异,最直接的是,选个基准值,定义两个列表(小值分区less和大值分区great),然后挨个比较,小的追加到less,大的追加到great

  再有就是,选个基准值,先从右边开始比,比基准值大的不管,比基准值小就和基准值换位置,换一次后,就去和左边比,比基准值小的不管,比基准值大的又去换位置,略有些绕。

  最后,还可以不递归,通过把分区节点保存在栈里来实现。

  

  1 # -*- coding: utf-8 -*-
  2 
  3 import numpy as np
  4 #1)依次对比arr[0]和其他元素,比arr[0]小的话,就原地删除,然后插入到arr[0]前面,基准值后移。大于等于,则不处理。然后递归
  5 #原地排序
  6 def quick_sort1(arr,left,right):
  7     
  8     if left>=right:
  9         return
 10     flag=left
 11     for i in range(left+1,right+1):
 12         if arr[flag]>arr[i]:
 13             temp=arr[i]
 14             del arr[i]
 15             arr.insert(flag,temp)
 16             flag+=1
 17     quick_sort1(arr,left,flag-1)
 18     quick_sort1(arr,flag+1,right)
 19 #2)基准值arr[0],对比所有元素,比它小就追加到less后面,比它大就追加到great后面,相等就追加到pivot后面,然后递归
 20 #返回排序后的列表
 21 def quick_sort2(arr):
 22     less=[]
 23     great=[]
 24     pivot=[]
 25     if len(arr)<=1:
 26         return arr
 27     else:
 28         p=arr[0]
 29         for i in arr:
 30             if i<p:
 31                 less.append(i)
 32             elif i>p:
 33                 great.append(i)
 34             else:
 35                 pivot.append(i)
 36         less=quick_sort2(less)
 37         great=quick_sort2(great)
 38         return less+pivot+great
 39 #2-2)基本思想同上,代码更简化
 40 def quick_sort22(arr):
 41     if len(arr)<=1:
 42         return arr
 43     else:
 44         return quick_sort22([i for i in arr[1:] if i<arr[0]])+[arr[0]]+quick_sort22([i for i in arr[1:] if i>=arr[0]])
 46 #2-3)思路同上,更简化的版本
 47 quick_sort23=lambda xs:((len(xs)<=1 and [xs]) or [quick_sort23([x for x in xs[1:] if x<xs[0]])+[xs[0]]+quick_sort23([x for x in xs[1:] if x>=xs[0]])])[0]
 49 quick_sort24=lambda arr:arr if len(arr)<=1 else quick_sort24([x for x in arr[1:] if x<arr[0]])+[arr[0]]+quick_sort24([x for x in arr[1:] if x>=arr[0]])

      #lambda 参数:取值1,如果满足条件1,否则,取值2 51 52 53 #3)定义两个函数:分区和排序。分区是要把列表元素移动位置,直到基准值arr[0]移到中间(左边都比它小,右边都比它大)。排序则调用分区并递归 54 #原地排序 55 def partition(arr,i,j): 56 p=arr[i] 57 while i!=j: 58 while i<j and p<=arr[j]:#此处添加=,解决了之前遇到的序列中有重复值时死循环的问题 59 j-=1 60 arr[i]=arr[j] 61 while i<j and p>arr[i]: 62 i+=1 63 arr[j]=arr[i] 64 arr[i]=p 65 return i 66 def quick_sort3(arr,i,j): 67 if i<j: 68 mid=partition(arr,i,j) 69 quick_sort3(arr,i,mid-1) 70 quick_sort3(arr,mid+1,j) 71 #3-2)上述思路的变体,分区函数变动,每次都比右边是否比基准值大,大的话,j前移,否则,把arr[j]给到arr[i],然后i后移,arr[i]再给到arr[j],继续上述循环 72 def partition2(arr,i,j): 73 p=arr[i] 74 while i!=j: 75 while i<j and p<=arr[j]: 76 j-=1 77 78 while i<j and p>arr[j]: 79 arr[i]=arr[j] 80 i+=1 81 arr[j]=arr[i] 82 arr[i]=p 83 return i 84 def quick_sort32(arr,i,j): 85 if i<j: 86 mid=partition2(arr,i,j) 87 quick_sort32(arr,i,mid-1) 88 quick_sort32(arr,mid+1,j) 89 #3-3)分区函数变动,基准值为最后一个值,依次比较,如果比基准值小,就换到前面去,最后再把基准值换到中间。 90 def partition3(arr,i,j): 91 p=arr[j] 92 x=i-1 93 for y in range(i,j): 94 if arr[y]<=p: 95 x+=1 96 arr[x],arr[y]=arr[y],arr[x] 97 arr[x+1],arr[j]=arr[j],arr[x+1] 98 return x+1 99 def quick_sort33(arr,i,j): 100 if i<j: 101 mid=partition3(arr,i,j) 102 quick_sort33(arr,i,mid-1) 103 quick_sort33(arr,mid+1,j) 104 #4)非递归方式,使用栈,思路类似previous,只是把切分边界保存在栈(用list实现)里, 105 #当只剩一个元素时,跳出本次循环,进入下次循环,看下一个区间里元素值是否多于1个,直到栈空 106 def quick_sort4(arr,i,j): 107 if j<=i: 108 return 109 stack=[] 110 stack.extend([i,j]) 111 while stack: 112 left=stack.pop(0) 113 right=stack.pop(0) 114 if right<=left: 115 continue 116 x=left-1 117 p=arr[right] 118 for y in range(left,right):#此处循环不包括最后一个元素,循环结束后,最后一个元素换到中间 119 if arr[y]<=p: 120 x+=1 121 arr[x],arr[y]=arr[y],arr[x] 122 arr[x+1],arr[right]=arr[right],arr[x+1] 123 stack.extend([left,x,x+2,right]) 124 125 126 if __name__=="__main__": 127 s=np.random.randint(1,30,20).tolist() 128 print(s) 129 #print(quick_sort24(s)) 130 quick_sort4(s,0,len(s)-1) 131 print(s)
原文地址:https://www.cnblogs.com/xiaoxiong-kankan/p/8522524.html