秋招过去好久了,闲来无事,突然想到一个问题,就是他们总喜欢问快排,当然快排应该是比较简单的啦。当你实现的时候,他们大多会问,非递归的实现,这个就会难到一部分同学哈,我也是。现在总结一下。
快速排序递归实现:
先看一下,这个《数据结构教程》李春葆 第5版,提供的代码(语言是C/C++),递归版的(简练),原理就不解释了:
void QuickSort(RecType R[],int s,int t)
{//对R[s]至R[t]的元素进行快速排序
int i=s,j=t;
RecType tmp;
if (s<t) //区间内至少存在2个元素的情况
{
tmp=R[s]; //用区间的第1个记录作为基准
while (i!=j) //两端交替向中间扫描,直至i=j为止
{
while (j>i && R[j].key>=tmp.key)
j--;
R[i]=R[j];
while (i<j && R[i].key<=tmp.key)
i++;
R[j]=R[i];
}
R[i]=tmp;
QuickSort(R,s,i-1); //对左区间递归排序
QuickSort(R,i+1,t); //对右区间递归排序
}
//递归出口:不需要任何操作
}
Python 递归版本:
# @Time :2023/09/10
# @Author :Liu
# 快速排序 递归
def QuickSort(nums, left, right):
if left >= right: # 区间内至少存在2个元素的情况
return
i, j = left, right
pivot = nums[i] # 用区间的第1个记录作为基准
while i != j: # 两端交替向中间扫描,直至i=j为止
while j > i and nums[j] >= pivot:
j -= 1
nums[i] = nums[j]
while i < j and nums[i] <= pivot:
i += 1
nums[j] = nums[i]
nums[i] = pivot
QuickSort(nums, left, i-1) # 对左区间递归排序
QuickSort(nums, i+1, right) # 对右区间递归排序
if __name__ == '__main__':
nums = [10, 7, 8, 9, 1, 5, 11]
n = len(nums)
QuickSort(nums, 0, n - 1)
print(nums)
快速排序非递归的实现:
现在重点介绍一下非递归的方法,很显然,需要借助栈来实现。具体原理如下:
(1)我们找一个基准进行一趟快排,一般
会产生两个区间,这时,可以用一个栈保存这两个区间(区间类型[start, end]
)。很显然,现在已经归位一个元素
了。
(2)循环判断栈
,出栈,也就是拿出一个区间,继续一趟快排,再归位一个元素
,然后再判断产生的区间入栈
。
(3)直到栈为空,此时已经说明列表,排序好了。
Python实现代码:
# @Time :2019/01/21
# @Author :LiuYinxing
# 快速排序 栈
def QuickSort(arr): # 模拟栈操作实现非递归的快速排序
if len(arr) < 2:return arr
stack = []
stack.append([0, len(arr)-1]) # 初始化栈
while stack:
l, r = stack.pop() # 出栈一个区间
index = partition(arr, l, r) # 对分区进行一趟交换操作,并返回基准线下标
if l < index - 1:
stack.append([l, index - 1]) # 当前趟,左区间入栈
if r > index + 1:
stack.append([index + 1, r]) # 当前趟,右区间入栈
def partition(arr, s, t): # 对分区进行一趟交换操作,并返回基准线下标
tmp = arr[s] # 用区间的第1个记录作为基准
while s < t:
while s < t and arr[t] >= tmp: t -= 1
arr[s] = arr[t]
while s < t and arr[s] <= tmp: s += 1
arr[t] = arr[s]
# 此时s = t
arr[s] = tmp
return s
if __name__ == '__main__':
arr = [4, 5, 0, -2, -3, 1]
QuickSort(arr)
print(arr)
声明: 总结学习,有问题或不当之处,可以批评指正哦,谢谢。
[1] 非递归代码参考链接