• 使用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)
  • 相关阅读:
    查看数据库表中的数据
    exec和execsql
    CPI
    百度硬盘可以检索的字节测试
    HDU2095
    Vigenere密码
    斌神无所不能
    HDU p1017
    POJ1316
    head区的代码详解
  • 原文地址:https://www.cnblogs.com/xiaoxiong-kankan/p/8522524.html
Copyright © 2020-2023  润新知