【数据结构】——快速排序

 

目录

一、代码

二、复杂度:O(nlog(n))

三、快速排序的劣势


视频参考链接:https://www.bilibili.com/video/BV1mp4y1D7UP?p=17

一、代码

'''
思想:假设是对一个list进行排序
1、选取第一个元素作为p元素;
2、将p元素归位,即将小于p元素的元素放在列表左边,将大于p元素的元素放在列表右边
3、通过2实现了p元素的归位,这样就将列表分成了两个子列表,对左右两个子列表重复使用1、2步骤,实现快速排序
'''
import time

def partition1(li:list,left:int,right:int)->int:
	'''这是根据路飞商城的思路来的
	将p元素归位的函数:取第一个元素为p元素,移动right,若right指针的值大于P,
	则right继续往左移动,否则停止移动,将值赋值给left所在的位置;然后再移动left,
	若left指针的值小于P,则left继续往右移动,否则停止移动,将值赋值给right所在的位置;
	如此交替移动,直到left=right时,停止,并将P值赋值给left(right)
	:param li: 需要归位的列表
	:param left: 列表左指针索引,初始值为0
	:param right: 列表右指针索引,初始值为len(li)-1
	:return: 返回p归位的索引
	'''
	#得到要归位的元素(第一个元素)
	p = li[left]
	#当列表有两个元素时,才进行排序
	while left < right:# 保证有两个元素
		#这里我们从列表的右边开始进行元素的比较
		while left < right and p <= li[right]: # 至少两个元素并且p元素值小于等于right指针指向的值时,右指针左移
			right -= 1 # right 左移一步
		li[left] = li[right] # 不满足上述循环条件时,停止移动right,并且将right上的值赋值给left
		#右指针停止移动后,开始进行左指针的移动
		while left < right and p >= li[left]:
			left += 1
		li[right] = li[left]
	#当left = right时,说明已经归位了,将p赋值给归位位置
	li[left] = p
	return left

def quickSorted1(li,left,right):
	'''
	对列表进行快排
	:param li: 需要排序的列表
	:param left: 左索引
	:param right: 右索引
	:return: 返回排好序的列表
	'''
	if left < right:
		mid = partition1(li, left, right)  # 首先得到第一个归位索引
		# 对左边列表进行排序
		quickSorted1(li,left,mid-1)
		# 对右边列表进行排序
		quickSorted1(li,mid + 1,right)


#-----------------------------------------------------------------------


def partition2(li,left,right):
	'''
	这个的主要思路是自己的思路
	主要思路就是左右交替进行比较,然后将没有元素的位置赋值为None,如当p>右指针的值时,先将right的值赋值给left,
	再将right值赋值为None,
	:param li: 
	:param left: 
	:param right: 
	:return: 
	'''
	p = li[left]
	li[left] = None
	while left < right:
		if li[left] == None: # 若检测到左指针为空时
			if p > li[right]: # 若p元素大于right指向的值时
				li[left] = li[right] # 将right值赋值给left
				li[right] = None # 此时right为空
				print(li,"right")
			else:
				right -= 1 # 若p元素小于right值,则right左移
		else:
			if p < li[left]: # 若p元素小于left指向的值时
				li[right] = li[left] # 将left值赋值给right
				li[left] = None # 此时left为空
				print(li, "left")
			else:
				left += 1 # 若p元素大于left值,则left右移
	li[left] = p
	return left

def quickSorted2(li,left,right):
	'''
	对列表进行快排
	:param li: 需要排序的列表
	:param left: 左索引
	:param right: 右索引
	:return: 返回排好序的列表
	'''
	if left < right:
		mid = partition2(li, left, right)  # 首先得到第一个归位索引
		# 对左边列表进行排序
		quickSorted2(li,left,mid-1)
		# 对右边列表进行排序
		quickSorted2(li,mid + 1,right)

li = [5,7,4,6,3,1,2,9,8]
startTime1 = time.time()
quickSorted1(li,0,len(li)-1)
endTime1 = time.time()
print(li,"method1")
print("method1用时:%9f"%(endTime1-startTime1))

#-----------------------------------------------------

startTime2 = time.time()
quickSorted2(li,0,len(li)-1)
endTime2 = time.time()
print(li,"method2")
print("method2用时:%9f"%(endTime2-startTime2))

二、复杂度:O(nlog(n))

当需要排序的元素个数少的时候,二者的运算速度没有什么区别,但是当数字为10000的时候,就会发生比较大的差别

第一种方法:0.04897332191467285

第二种方法:直接就报递归栈溢出的错误了。。。“进程已结束,退出代码-1073741571 (0xC00000FD)”

三、快速排序的劣势

1、对于Python会有递归最大深度的限制

2、在对一组倒序的列表进行正序时,其复杂度接近于O(n^2)

解决方法:

a、每一次随机从列表中抽取一个元素作为p元素;

b、在进行排序前,先打乱列表再进行排序,这其实是很奇妙的,通过打乱顺序来提高效率,第一次听说,但是它就是达到了这种效果,amazing~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有情怀的机械男

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值