快速排序的python实现(超赞的python思维)
最近看了下快排算法,感觉挺牛逼的,于是就尝试着自己实现一下。不试不知道,一试吓一跳,原来快排还可以这么简单的去理解和实现;
快排算法思想
选取快排的基准,选择基准的目的是为了将待排序列不断的划分为两堆,怎么说,其实这和D&C(分治法)的思想并无差异,不断的用基准将序列划分到小于两个个元素时,此时基准的左边比基准小,右边比基准大,自然就把序排好了不是吗!然后再一步一步的回溯到完整序列,整个序列的就按由小到大的顺序排好了
分治法解快排
确定基条件
所谓基条件就是判断递归调用退出的标准。这里是序列划分到小于两个元素时,直接返回该序列。
缩小问题规模
不断的将序列按基准划分。
-
选取基准
一般选序列的第一个元素作为基准
-
按基准将序列划分为两堆
- 第一步:基准在左边第一位,因此我们首先用“哨兵”对序列从右往左扫描,一旦发现有比基准大的,就先停下来;
- 第二步: 再用“哨兵”对序列从左往右扫描,一旦发现有比基准小的,就先停下来;
- 第三步: 将两个哨兵处的元素交换
- 第四步: 检查两个“哨兵”是否相遇,如果没有则重复前三步;如果相遇,则将相遇处元素与第一个位置交换位置。划分完成。
递归调用自身
将划分好的左右两堆序列分别传入到自身函数里,继续划分。
Don’t be shit, show me code
- 写法一: 我们用C++的思维将快排的思想用python实现一遍
####################################################
# 写法一: 我们用C++的思维将快排的思想用python实现一遍
####################################################
def quicksort(a, left, right):
'''
快排的普通思维实现
:param a:
:param left:
:param right:
:return:
'''
# 确定基条件
if left>right:
return
# 申明需要用到的变量
temp = a[left]
i = left
j = right
# 交换中间变量
t = temp
# 缩小问题规模
# 在左右指针相遇之前完成所有交换,用基准将数组分为两组
while i != j:
# 先从右往左扫描,遇到比基准小的便停下来
while a[j]>=temp and i<j:
j -= 1
# 在从左往右扫描,遇到比基准大的数便停下来
while a[i]<=temp and i<j:
i += 1
# 左右交换
t = a[j]
a[j] = a[i]
a[i] = t
# 左右指针相遇,将基准放到数组中间将数组划分为两块
a[left] = a[i]
a[i] = temp
# print(a)
# 调用递归
quicksort(a, left, i-1)
quicksort(a, i+1, right)
- 写法二:人生苦短,下面展示一种python实现快排的超简单写法
####################################################
# 法二:人生苦短,下面展示一种python实现快排的超简单写法
####################################################
def quecksort_breif(a):
'''
NB的python思维实现
:param a:
:return:
'''
# 确定基条件
if len(a) < 2:
return a
else:
# 选择基准
povit = a[0]
# 确定基准的左边
less = [i for i in a[1:] if i <= povit]
# 确定基准的右边
greater = [i for i in a[1:] if i > povit]
# 递归调用
return quecksort_breif(less) + [povit] + quecksort_breif(greater)
- 执行和结果
if __name__ == "__main__":
a = [6,8,2,3,4,5,7]
print("一般思维快排")
quicksort(a,0,len(a)-1)
print(a)
print("python思维快排")
print(quecksort_breif(a))
一般思维快排
[2, 3, 4, 5, 6, 7, 8]
python思维快排
[2, 3, 4, 5, 6, 7, 8]