各种排序整理
速查:
以下的排序用python来实现,比较方便
这个图是真的棒!一定要给抄过来哈哈哈哈哈,特地放一下原地址
众所周知 快排的 平均时间复杂度 和 最优时间复杂度 都是:O(nlogn),
最坏情况下(元素基本有序):O( n^2 )
快排(quick sort)采用了分治的思想,个人觉得用递归来概括也是可以的。
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
具体方法:
def quickSort(targetlist, left ,right):
if left>right:
return
pivot = targetlist[left] # pivot是基准
i = left
j = right
while(i < j):
# 如果right一直大于pivot,则继续走 直到找到比pivot小的
while(targetlist[j] >= pivot and i<j):
j -=1
while(targetlist[i] <= pivot and i<j):
i+=1
# 此时right < pivot,left > pivot, 将i和j做交换
if(i < j): # 这里做判断是为了right到了left位置时,不用再将执行下面这三行代码了
temp = targetlist[i]
targetlist[i] = targetlist[j]
targetlist[j] = temp
# left和right相遇了
# 将相遇点的元素和pivot做交换
targetlist[left] = targetlist[j]
targetlist[j] = pivot
print(targetlist)
# 对于基准点两边的元素分别在做排序
quickSort(targetlist, left,j-1) # 递归
quickSort(targetlist, j+1,right)
if __name__ == "__main__":
target = [180,183,187,182,55,123,490,999,2]
quickSort(target,0,len(target)-1)
print(target)
或者借用lambda表达式 一行代码...也行,下面代码结果是升序的
quick_sort = lambda array: array if len(array) <= 1 else quick_sort([
item for item in array[1:] if item <= array[0]
]) + [array[0]] + quick_sort([item for item in array[1:] if item > array[0]])
target = [180,183,187,182,55,123,490,999,2]
a = quick_sort(target)
print(a)
冒泡排序是一种比较容易理解的排序算法,它重复的访问比较要排序的元素列,一次比较两个相邻的元素,一层一层的将较大的元素往后移动,这种类似气泡在上升过程中慢慢变大效果的排序就是冒泡排序
一般来说,因为它需要双层循环n*(n-1)),所以平均时间复杂度为O(n^2)
改进后的算法这里不考虑。
"""冒泡排序"""
def bubbleSort(targetlist):
# 第一层for循环表示循环的遍数
for i in range(len(targetlist) -1):
# 第二层for表示具体比较哪两个元素
for j in range(len(targetlist) -1 -i):
if targetlist[j] > targetlist[j+1]:
# 如果前大后小,则交换
targetlist[j],targetlist[j+1] = targetlist[j+1],targetlist[j]
if __name__ == "__main__":
target = [180,183,187,182,55,123,490,999,2]
bubbleSort(target)
print(target)
没有找到更好的动图了好可惜
选择排序(selection sort)是一种简单直观的排序算法。每次从待排序的数据元素中选出最小(最大)的一个元素,存放在序列的起始位置,故而称为 选择排序
选择排序同样是双层循环n*(n-1)),所以时间复杂度也为:O(n^2)
该实现方法和冒泡方法有点像,都是双层循环
"""选择排序"""
def selectionSsort(targetlist):
# 第一层for表示循环选择的遍数
for i in range(len(targetlist) - 1):
# 将起始元素设为最小元素
min_index = i
# 第二层for表示最小元素和后面的元素逐个比较
for j in range(i + 1, len(targetlist)):
if targetlist[j] < targetlist[min_index]:
# 如果当前元素比最小元素小,则把当前元素角标记为最小元素角标
min_index = j
# 查找一遍后将最小元素与起始元素互换
targetlist[min_index], targetlist[i] = targetlist[i], targetlist[min_index]
if __name__ == "__main__":
target = [180,183,187,182,55,123,490,999,2]
selectionSsort(target)
print(target)
插入排序(Insertion-Sort)的算法描述也是一种简单直观的排序算法。主要时通过构建有序序列,对于未排序的数据,在已排序序列中从后向前扫描,找到相应的位置再插入。就像是在书架中插书:先找到相应位置,将后面的书往后推,再将书插入,如上图所示。
插入排序的适用场景:一个新元素需要插入到一组已经是有序的数组中,或者是一组基本有序的数组排序。
插入排序同样需要两次循坏一个一个比较,故时间复杂度也为O(n^2)
一次遍历排好一个元素
比较次数 | 列表 | 操作 |
---|---|---|
原始序列 | [180,183,187,182,55,123,490,999,2] | |
第一次比较后 | [180,183,187,182,55,123,490,999,2] | |
第二次比较后 | [180,183,187,182,55,123,490,999,2] | |
第三次比较后 | [180,182,183,187,55,123,490,999,2] | 182从后往前同黄色序列比较 |
第四次比较后 | [55,180,182,183,187,123,490,999,2] | 55 |
第五次比较后 | [55,123,180,182,183,187,490,999,2] | 123 |
第六次比较后 | [55,123,180,182,183,187,490,999,2] | |
第七次比较后 | [55,123,180,182,183,187,490,999,2] | |
第八次比较后 | [2,55,123,180,182,183,187,490,999] | 2 |
"""插入排序"""
def insertionSort(targetlist):
# 第一层for表示循环插入的遍数
for i in range(1, len(targetlist)):
# 设置当前需要插入的元素
current = targetlist[i]
# 与当前元素比较的比较元素
pre_index = i - 1
# 将所有当前元素之前的且大于当前元素的元素向后移动
while pre_index >= 0 and targetlist[pre_index] > current:
# 比较元素大于当前元素则把比较元素后移
targetlist[pre_index + 1] = targetlist[pre_index]
# 向前选择下一个比较元素,继续比较
pre_index -= 1
# 经过上面的一系列挪动,当比较元素小于当前元素,则将当前元素插入在其后面
targetlist[pre_index + 1] = current
if __name__ == "__main__":
target = [180,183,187,182,55,123,490,999,2]
insertionSort(target)
print(target)
需要区别于选择排序
当一个新元素需要插入到一组已经是有序的数组中,或者是一组基本有序的数组排序(而快排则是基本无序的情况下使用的)
其他特点
还有一些算法后面在更新,今天就先过掉这些基本算法
原文:https://www.cnblogs.com/ppppian2020/p/13110282.html