emmm...可怜的温中高二学子,星期六上了一天课,回到家持续学习算法还有洛伦兹力和解析几何等着我,看了4种排序算法,个人认为最后一种最难理解,先记下来,简单的冒泡排序,选择排序,插入排序再说吧,两周后要期中考了明天还要一早起来写卷子。快速排序属于较快的排序方法:
我可以先考虑假如我已经设计了一个算法partition(li,left,right):可以把第一个数取出,放到某一位置,使得该位置左侧的所有数皆小于这个数,该位置右侧所有数皆大于这个数,那么,我把这个列表以这个数为界,分为左右两边,分别在两边采用递归,就是再分成两部分而后分别完成类似步骤,最后一定可以达到整个序列的有序
接下来就是怎么使得paritition这个函数成立的过程,首先确定一个数tem(=5),然后把右箭头从右往左寻找比tem小的第一个遇到的数来填补左箭头处数字被“拿出”后的空缺,即有li[left]=li[right]
这时,右边这个坐标为right的数的位置空缺,所以左箭头从左往右去寻找第一个遇到的且比tem大的数扔到右边的right位置,即li[right]=li[left]
同理,左边空缺,右箭头继续向左移动,重复以上步骤,直到两箭头相遇且指向同一个空位,把这个空位填入tem,即可完成一次操作
算法实现:
1.partition函数
特点是程序还是比较对称性的,内层while的left小于right的限制条件是为了防止right一直向左走出左界线(或left一直向右走出右界线),跳出内层while的条件是左右箭头碰头或找到比tem小./大的值。(其他详情请看注释)
时间复杂度与效率
时间复杂度为O(nlogn):外层while为n,内层虽然两个while,却是left从左往右,right从右往左,相当于一共把列表扫了一遍,扫的次数是二分的次数如下图绘制,所以内层logn,两者相乘得nlogn下图为速度展示
总结与讨论
当然,考虑到最坏情况,如列表[9,8,7,6,5,4,3,2,1]使用快排则会使递归次数变多:
1.会超出递归最大深度 解决方法:调整递归最大深度
2.会增加时间复杂度最坏情况为O(n2) 解决方法:随机找一个数与每一轮的第一个数替换
(一个算法可以有两个时间复杂度如冒泡排序的最优时间复杂度为O(n)但仅有一种情况(已经顺序),平均时间复杂度为O(n))
自己做的程序
import time
start_time = time.time()
def partition(li,left,right):
tmp = li[left]
while left<right:
while left<right and tmp<=li[right]:
right-=1
li[left]=li[right]
while left<right and tmp>=li[left]:
left+=1
li[right]=li[left]
li[left] = tmp
return left
def quick_sort(li,left,right):
if left<right:
mid=partition(li,left,right)
quick_sort(li,mid+1,right)
quick_sort(li,left,mid-1)
return li
def _quick_sort(li,left,right):
quick_sort(li,left,right)
return li
li1=[6,5,2,9,8,7,4,1,3]
print(_quick_sort(li1,0,len(li1)-1))
end_time = time.time()
used_time= end_time - start_time
print(used_time)
运行结果显示:
后面显示的是时间,可见非常快
部分图片参考自b站IT编程界的扛把子的python算法学习视频,本文仅供个人学习使用,特此声明