冒泡排序
算法步骤
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
![冒泡排序](https://www.runoob.com/wp-content/uploads/2019/03/bubbleSort.gif)
分析与优化
时间复杂度,在数据完全有序的时候展现最优,为O(n);
其他情况下,n + (n-1) + ... + 2 + 1 ~ O(n^2)。
空间复杂度(就是在交换元素时那个临时变量所占的内存空间):冒泡排序的辅助变量空间仅仅是一个临时变量,并且不会随着排序规模的扩大而进行改变,所以空间复杂度为O(1)。
因此,算法在数据基本有序的情况下,性能最好。
要使算法在最佳情况下有O(n)复杂度,需要做一些改进,增加一个swap
的标志,当前一轮没有进行交换时,说明数组已经有序,没有必要再进行下一轮的循环了,直接退出。
代码
def bubbleSort(arr): #基本版
for i in range(1, len(arr)):
for j in range(0, len(arr)-i):
if arr[j] > arr[j+1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
参考资料
选择排序
时空复杂度与冒泡基本一致,可以认为选择排序是冒泡排序的一种改进。
算法步骤
- 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
- 从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
- 重复第二步,直到所有元素均排序完毕。
![选择排序](https://pic1.zhimg.com/v2-1c7e20f306ddc02eb4e3a50fa7817ff4_b.webp)
代码
test1.pydef selectionSort(arr): for i in range(len(arr) - 1): # 记录最小数的索引 minIndex = i for j in range(i + 1, len(arr)): if arr[j] < arr[minIndex]: minIndex = j # i 不是最小数时,将 i 和最小数进行交换 if i != minIndex: arr[i], arr[minIndex] = arr[minIndex], arr[i] return arr
(直接)插入排序
算法步骤
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
![插入排序](https://www.runoob.com/wp-content/uploads/2019/03/insertionSort.gif)
代码
def insertionSort(arr):
for i in range(len(arr)):
preIndex = i-1
current = arr[i]
while preIndex >= 0 and arr[preIndex] > current:
arr[preIndex+1] = arr[preIndex]
preIndex-=1
arr[preIndex+1] = current
return arr
希尔排序
希尔排序是插入排序的一种算法,是对直接插入排序的一个优化,也称缩小增量排序。希尔排序是非稳定排序算法。
算法步骤
![希尔排序示意图](shellsort.jpg)
![希尔排序示意图2](shellsort2.gif)
代码
ShellSort.pya = [99,5,69,33,56,13,22,55,77,48,12,88,2,69,99]#测试案例 b = len(a) #列表长度 gap = b // 2 #初始步长设置为总长度的一半 while gap >= 1: for i in range (gap,b): j = i while j>=gap and a[j-gap] > a[j]:#在每一组里面进行直接插入排序 a[j],a[j-gap] = a[j-gap],a[j] j-= gap gap=gap//2 #更新步长 print(a) #该方案中,多个组的插入排序是交替进行的(或叫同时进行)
归并排序
算法步骤
![归并排序](https://www.runoob.com/wp-content/uploads/2019/05/1557906108-5066-20161218163120151-452283750.png)
![归并排序](归并排序.gif)
归并排序的最好、最坏和平均时间复杂度都是O(nlogn),而空间复杂度是O(n),比较次数介于(nlogn)/2和(nlogn)-n+1,赋值操作的次数是(2nlogn)。因此可以看出,归并排序算法比较占用内存,但却是效率高且稳定的排序算法。
代码
def mergeSort(a): #归并排序
if len(a)<=1: #如果是一个元素或者空元素
return a
mid=len(a)//2 #去中间位置
left =mergeSort(a[:mid]) #归并左列表
right=mergeSort(a[mid:]) #归并右列表
return merge(left,right) #返回
def merge(left,right): #合并两个列表
merged=[]
i,j=0,0 #i和j分别作为left和right的索引
left_len,right_len=len(left),len(right)#左右子列表的长度
while i<left_len and j<right_len: #循环归并左右子列表元素
if left[i]<=right[j]:
merged.append(left[i]) #归并左列表
i+=1
else:
merged.append(right[j]) #归并右列表
j+=1
merged.extend(left[i:]) #归并剩余左列表
merged.extend(right[j:]) #归并剩余右列表
# print(left,right,merged) #跟踪调试
return merged
发表您的看法