Python双指针法,快速排序,这次不要再忘了

双指针法来实现快速排序

流程

  • 每轮都设定一个pivot枢轴,将所有小于pivot的元素都移到其左边,将所有大于pivot的元素都移到其右边。

经过这样处理后,这个pivot位置就不动了,所在位置就是它最后排好序的位置了。再分别递归处理pivot左边和右边的部分。

  • 要达成上述的效果,每轮处理过程分两步走:1.用双指针调整元素之间的位置 2.交换左右指针重合位置的与元素和pivot。 所用的双指针法有点像剑指 Offer 21. 调整数组顺序使奇数位于偶数前面,也是指针分别从头尾出发,但判断条件就不那么复杂,只需分别比较左右指针对应的两个数和pivot的大小关系。
  • 划重点!!! 语句顺序和pivot的选取相关!!!
  • 因为要交换左右指针所指,所以左指针从左出发,找大于pivot的,找到了就停住。同理右指针从右出发,找到小于pivot的,也停住,然后交换左右指针所指的元素。这个分别停住再交换的过程循环进行,直到左右指针重叠。这些交换中的最后一次交换,是在左右指针重叠时的交换,换言之,根本没交换!!!

指针移动肯定是用while语句了。那么每次左指针和右指针,谁先出发?

  • pivot选区间最左端的元素,就右指针先出发。 因为右指针最后停住的位置比pivot小,左指针过来和右指针汇合后,把这个比pivot小的元素和pivot交换,这样能保证这个小一点的元素在pivot左边,pivot的位置是正确的。
  • 同理,pivot选区间最右端的元素,就左指针先出发。 左指针停住的位置比pivot大,右指针过来和它汇合后,就将这个比pivot大的元素交换到pivot的右边了。

例子:选最左端元素5为pivot,应该右指针先出发。左右指针停在元素4的位置,交换4和5,pivot即5被移动到了正确的位置。倘若左指针先出发,左右指针会停在6的位置,此时若交换,6就跑到5的左边了,显然错误。

[5, 1, 2, 3, 4, 6, 7, 8, 9]

代码

分函数写,这个函数的功能是:将pivot交换到正确的位置,并且返回pivot交换后的位置,便于之后递归。

def partition(lst, left, right):
	start = right
	pivot = lst[start]
	while left != right:
		#只要大的,小于等于的都略过
	    while(left < right and lst[left] <= pivot):
	        left += 1
	    #只要小的,大于等于的都略过
	    while(left < right and lst[right] >= pivot):
	        right -= 1
	    lst[left], lst[right] = lst[right], lst[left]
	lst[start], lst[left] = lst[left], lst[start]
	return left

pivot要是选取左边,代码就应该这样写:

def partition(lst, left, right):
	start = left
	pivot = lst[start]
	while left != right:
	    #只要小的,大于等于的都略过
	    while(left < right and lst[right] >= pivot):
	        right -= 1
	    #只要大的,小于等于的都略过
	    while(left < right and lst[left] <= pivot):
	        left += 1
	    lst[left], lst[right] = lst[right], lst[left]
	lst[start], lst[left] = lst[left], lst[start]
	return left

快排的递归部分:

def kuaisu(lst, left, right):
	if left >= right:  #大于也行
	    return
	q = partition(lst, left, right)
	kuaisu(lst, left, q - 1)
	kuaisu(lst, q + 1, right)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值