目录
1、冒泡排序
1.1 思路概述
以升序排序为例,依次对未排序部分两两比较,元素大的放后面,元素小的放前面。每一轮下来,未排序中最大的元素会被冒到未排序区域的最后一个位置,每一轮都会确定当前最大元素的最终位置,该元素确定后,就会从未排序元素中剔除。如果其中某一轮,没有发生元素交换,说明整个未排序数组都已经有序,则完成排序。
1.2 复杂度分析
最好的情况是已经有序,则一轮结束,时间复杂度为O(n).最坏情况是逆序排序,则共需要经过n轮排序,每次复杂度为O(n),故时间复杂度为O(n^2). 由于是就地排序,故空间复杂度为O(1)。
1.3 适用场景
冒泡排序思路简单直观,但是复杂度较大,适用于数据规模较小的数据集。且由于其属于部分排序法,即每一轮都能确定一个元素的正确位置,因此可以用于求Topk问题,求Topk复杂度为O(kn)=O(n)
1.4 可视化步骤
1.5 Python代码
def BubbleSort(arr):
size=len(arr)
for i in range(0,size):
ordered = True #只要某一轮一整轮都没有发生任何交换,说明已经有序
for j in range(0,size-i-1):
if arr[j]>arr[j+1]:
arr[j],arr[j+1] = arr[j+1],arr[j]
ordered = False #只要发生了交换,说明仍然无序
if ordered = True:
return
2. 插入排序
2.1 思路概述
插入排序(InsertionSort),一般也被称为直接插入排序。它的基本思想是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增 1 的有序表。在实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素进行循环,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。
2.2 复杂度分析
插入排序的最好的情况下是已经有序,时间复杂度是 O(n),最坏情况逆序时复杂度为O(n^2),由于是原地排序,故空间复杂度为常数阶 O(1)。
2.3 适用场景
插入排序是一种最简单的排序方法,但是时间复杂度比较大,故可以用于少量元素的排序,它是一个有效的算法。但和冒泡排序不同,插入排序不属于部分排序,即并不是每一轮操作都能确定下一个元素的正确位置,只有当插入排序完成以后,才会有有意义的结果。
2.4 可视化步骤
2.5 Python代码
def InsertSort(arr):
for i in range(1,len(arr)): # 从第二个元素开始,因为第一个元素已经有序
key = arr[i]
j = i-1
while j>=0 and key<arr[i]: # 已排序区从右到左与待插入元素比较,直到已排序区域出现比待插入元素小的元素为止
arr[j+1] = arr[j] # 比待插入元素大的元素向右挪,给待插入元素留出位置
j -= 1
arr[j+1] = key #将待插入元素赋值给留出的空位
3. 选择排序
3.1 思路概述
通过线性排序,找到待排序区域的最小值,将其放到待排序区第一个位置。
3.2 复杂度分析
每次找待排序区的最小值的时间复杂度为O(n),由于要找n次最小值,故时间复杂度为O(n^2),由于只有完整遍历待排序区才能找出最小值,故无论数组有序无序,即最好和最坏情况下,时间复杂度都为O(n^2)。由于是原地排序,故空间复杂度为O(1)。
3.3 适用场景
由于不管何时,复杂度都是O(n^2),故只能用于小规模数据。但由于其是部分算法,故也可以用于TopK问题,时间复杂度是O(Kn)=O(n).