快速排序的三种算法
1. 分治法快速排序算法(左边)
使用分治法(Divide and conquer)策略来把一个序列(list)分为较小和较大的2个子序列,然后递归地排序两个子序列。
算法原理:
初始状态 {46 31 65 98 76 13 27}
进行一次快速排序之后划分为 {27 31 13} 46 {76 98 65}
分别对前后两部分进行快速排序 {27 31 13} 经第三步和第四步交换后变成 {13 27 31} 完成排序。
{76 98 65} 经第三步和第四步交换后变成 {65 76 98} 完成排序。
def target(arr,low,high): # arr[]:排序数组 low: 起始索引 high:结束索引
i=low-1 #最小元素索引
privo=arr[high] #结束索引位置的具体值
for j in range(low,high): #遍历索引
if arr[j]<=privo: # 当前元素小于或等于pivot
i=i+1
arr[i],arr[j]=arr[j],arr[i] #交换当前元素位置
arr[i+1],arr[high]=arr[high],arr[i+1] #交换i下一个元素与末尾元素
return i+1
def quickSort(arr,low,high): #快速排序函数
if low<high:
pi=target(arr,low,high) #调用target函数
quickSort(arr,low,pi-1) #分界值左边的子列表
quickSort(arr,pi+1,high) #分界值右边的子列表
arr=[46 31 65 98 76 13 27]
n=len(arr) #计算数组arr长度
quickSort(arr,0,n-1) #给快速排序函数赋值
print("通过快速排序后的顺序为:")
for i in range(n): #遍历元素
print(arr[i])
2.随机快速排序算法
我们通过使用随机化的快速排序随机的从数列中选取一个元素与第一个,或者最后一个元素交换,这样就会使得数列有序的概率降低。所以随机快速排序平均速度是比快速排序要快的。因为随机化快速排序的平均时间复杂度为O(nlogn),最坏时间时间也会达到O(n^2),这种机率已经降得很小。
代码如下
import random #导入随机数
def quicksort(arr, firstIn, lastIn): #定义快速排序函数
if firstIn < lastIn: #判断起始索引小于结束索引
divIn = random_partition(arr, firstIn, lastIn) #产生随机分界值
quicksort(arr, firstIn, divIn) #将分界值左边子列表排序
quicksort(arr, divIn + 1, lastIn)#将分界值右边子列表排序
else:
return
def partition(arr, firstIn, lastIn): #定义划分函数
i = firstIn - 1 #最小元素索引
for j in range(firstIn, lastIn): #遍历索引
if arr[j] <= arr[lastIn]: # 当前元素小于或等于末尾元素
i = i + 1 #索引加1
arr[i], arr[j] = arr[j], arr[i] #交换当前元素位置
arr[i + 1], arr[lastIn] = arr[lastIn], arr[i + 1] #交换i下一个元素与末尾元素
print(arr) #打印
return i
def random_partition(arr, firstIn, lastIn): #定义随机划分函数
i = random.randint(firstIn, lastIn) #生成随机索引在有效范围内
arr[i], arr[lastIn] = arr[lastIn], arr[i]#当前随机索引元素与末尾元素交换
return partition(arr, firstIn, lastIn) #返回给划分函数
arr = [1, 4, 34, 44, 23, 76, 2] #定义一组数据
print(arr[len(arr) - 1]) #打印末尾元素
print("initial array:\n", arr) #打印初始数组
quicksort(arr, 0, len(arr) - 1) #调用快速排序函数进行排序
print("result array:\n", arr) #打印排序后的结果
3.递归快速排序算法(右边)
算法原理:
lista = [8,5,1,34,19,20,33,11]
第一次划分:
第一次交换:j=0 :判断lista[0]<=lista[len-1] #遍历数组
[8,5,1,34,19,20,33,11] i=0 #记录划分位置
第二次交换:j=1 判断lista[1]<=lista[7]
[8,5,1,11,19,20,33,34] i=1 #记录划分位置
第三次交换:j=1 判断lista[2]<=lista[7]
[1,5,8,11,19,20,33,34] i=2 #记录划分位置
lista = [8,5,1,34,19,20,33,11]
def quikSwith(listArr,left,right):
'''
@参数:listArr是需要排序的列表
left是起始位置
right是结束位置
'''
div = listArr[right] #分界值用于划分,默认取最后一个元素
position = left #记录划分的索引
for i in range(left,right): #用列表中的其他元素与分界值比较
if listArr[i] > div: #大于分界值,不作任何操作
position=i #position不变
pass
else:
#小于分界值时,交换划分和元素的位置
listArr[i],listArr[position]=listArr[position],listArr[i]
position += 1 #划分位置后移一位
pass
print(lista) #检验过程
pass
#退出循环后划分位置与分界值交换
listArr[position],listArr[right]=listArr[right],listArr[position]
print(lista)
return position #返回记录的位置
pass
def quikSort(listArr,left,right):
if left >= right: #退出条件
return None
position = quikSwith(listArr,left,right) #继续划分,直到只有一个数或没有数
quikSort(listArr,left,position - 1) #前半部分子列表
quikSort(listArr,position + 1,right) #后半部分子列表
pass
print(quikSort(lista,0,len(lista)-1)) #调用快速排序函数并打印
print(lista)
如有纰漏,请多指教