目录
一、代码
二、复杂度:O(nlog(n))
三、快速排序的劣势
视频参考链接:https://www.bilibili.com/video/BV1mp4y1D7UP?p=17
一、代码
'''
思想:假设是对一个list进行排序
1、选取第一个元素作为p元素;
2、将p元素归位,即将小于p元素的元素放在列表左边,将大于p元素的元素放在列表右边
3、通过2实现了p元素的归位,这样就将列表分成了两个子列表,对左右两个子列表重复使用1、2步骤,实现快速排序
'''
import timedef 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 += 1li[right] = li[left]#当left = right时,说明已经归位了,将p赋值给归位位置li[left] = preturn leftdef 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] = Nonewhile left < right:if li[left] == None: # 若检测到左指针为空时if p > li[right]: # 若p元素大于right指向的值时li[left] = li[right] # 将right值赋值给leftli[right] = None # 此时right为空print(li,"right")else:right -= 1 # 若p元素小于right值,则right左移else:if p < li[left]: # 若p元素小于left指向的值时li[right] = li[left] # 将left值赋值给rightli[left] = None # 此时left为空print(li, "left")else:left += 1 # 若p元素大于left值,则left右移li[left] = preturn leftdef 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~