QuickSort 快速排序
借鉴《啊哈!算法》这本萌书和python菜鸟教程的想法。
leetcode 75 也是快排思想题。
思想:
- 挑选基准值:从数列中挑出一个元素,称为"基准"(pivot);
- 分割:重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(与基准值相等的数可以到任何一边)。在这个分割结束之后,对基准值的排序就已经完成;
- 递归排序子序列:递归地将小于基准值元素的子序列和大于基准值元素的子序列排序。
递归到最底部的判断条件是数列的大小是零或一,此时该数列显然已经有序。
选取基准值有数种具体方法,此选取方法对排序的时间性能有决定性影响。
《啊哈!算法》里的具体代码步骤:
代码1:
# 快速排序函数
def quickSort(data):
if len(data)>=2:
left=[]
right=[]
pivot=data[0]
for d in data[1:]:
if d<=pivot:
left.append(d)
else:
right.append(d)
return quickSort(left)+[pivot]+quickSort(right)
else:
return data
代码2:
def partition(arr,low,high):
i=low-1
pivot=arr[high]
for j in range(low,high):
# 当前元素小于或等于 pivot
if arr[j] <= pivot:
i+=1
arr[i],arr[j] = arr[j],arr[i] #列表中两元素位置交换
arr[i+1],arr[high] = arr[high],arr[i+1]
return ( i+1 )
# arr[] --> 排序数组
# low --> 起始索引
# high --> 结束索引
# 快速排序函数
def quickSort(arr,low,high):
if low<high:
pi=partition(arr,low,high) #pi是基准值最后排在的位置
quickSort(arr,low,pi-1)
quickSort(arr,pi+1,high)
时间复杂度:
最坏情况下的快排时间复杂度: O(n ^2)
最坏情况发生在划分过程每一次产生的俩个区域分别包含n-1个元素和一个0元素。T(N)=T(N-1)+T(0)+O(N)=T(N-1)+O(N)。T(N)=(T(N-2)+O(N-1))+O(N)=T(N-2)+O(N-1)+O(N)=…=T(0)+O(1)+O(2)+…+O(N)=1/2*O(N ^2)
最好情况下快排时间复杂度:O(nlogn)
最好情况下,每一个子问题的大小为n/2。.
T(N)=2T(N/2)+O(N)=2*(2T(N/4)+O(N/2))+O(N)=4T(N/4)+2O(N)=8T(N/8)+3O(N)=…=NT(1)+logN O(N)=O(N)+O(NlogN)=取大的 O(NlogN)
空间复杂度:
最优的情况下空间复杂度为:O(logn)
最差的情况下空间复杂度为:O( n ) 退化为冒泡排序的情况
稳定性:
快速排序是不稳定的算法,它不满足稳定算法的定义。
算法稳定性: 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面,则这个排序算法是稳定的。