冒泡法
冒泡排序(Bubble Sort)是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
作为最简单的排序算法之一,冒泡排序给我的感觉就像 Abandon 在单词书里出现的感觉一样,每次都在第一页第一位,所以最熟悉。冒泡排序还有一种优化算法,就是立一个 flag,当在一趟序列遍历中元素没有发生交换,则证明该序列已经有序。但这种改进对于提升性能来说并没有什么太大作用。
1. 算法步骤
-
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
-
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
-
针对所有的元素重复以上的步骤,除了最后一个。
-
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
2. 动图演示
-
python代码实现
li = [2,23,4,6,38,5,65,7,1,45,32] for j in range(len(li)-1): for i in range(len(li)-1-j): if li[i] > li[i+1]: li[i],li[i + 1] = li[i+1],li[i] print(li) 结果: [2, 4, 6, 23, 5, 38, 7, 1, 45, 32, 65] [2, 4, 6, 5, 23, 7, 1, 38, 32, 45, 65] [2, 4, 5, 6, 7, 1, 23, 32, 38, 45, 65] [2, 4, 5, 6, 1, 7, 23, 32, 38, 45, 65] [2, 4, 5, 1, 6, 7, 23, 32, 38, 45, 65] [2, 4, 1, 5, 6, 7, 23, 32, 38, 45, 65] [2, 1, 4, 5, 6, 7, 23, 32, 38, 45, 65] [1, 2, 4, 5, 6, 7, 23, 32, 38, 45, 65] [1, 2, 4, 5, 6, 7, 23, 32, 38, 45, 65] [1, 2, 4, 5, 6, 7, 23, 32, 38, 45, 65]
选择排序
选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。
1. 算法步骤
-
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
-
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
-
重复第二步,直到所有元素均排序完毕。
2. 动图演示
python代码实现
li = [2,23,4,6,38,5,65,7,1,45,32] #选择排序 for j in range(len(li)): for i in range(j,len(li)): if li[j] > li[i]: li[j],li[i] = li[i],li[j] print(li) 结果: [1, 2, 4, 5, 6, 7, 23, 32, 38, 45, 65]
插入排序
插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
插入排序和冒泡排序一样,也有一种优化算法,叫做拆半插入。
1. 算法步骤
-
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
-
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
python代码实现
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
快速排序
1. 算法步骤
-
从数列中挑出一个元素,称为 “基准”(pivot);
-
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
-
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
2. 动图演示
python代码实现
1 # import sys 2 # sys.setrecursionlimit(1000000) 3 4 def quick_sort(data): 5 d = [[], [], []] 6 d_pivot = data[-1] # 因为是乱序数组,所以第几个都是可以的,理论上是一样的 7 for i in data: 8 if i < d_pivot: # 小于基准值的放在前 9 d[0].append(i) 10 elif i > d_pivot: # 大于基准值的放在后 11 d[2].append(i) 12 else: # 等于基准值的放在中间 13 d[1].append(i) 14 15 # print(d[0], d[1], d[2]) 16 if len(d[0]) > 1: # 大于基准值的子数组,递归 17 d[0] = quick_sort(d[0]) 18 19 if len(d[2]) > 1: # 小于基准值的子数组,递归 20 d[2] = quick_sort(d[2]) 21 22 d[0].extend(d[1]) 23 d[0].extend(d[2]) 24 return d[0] 25 26 27 if __name__ == "__main__": 28 d0 = [2, 15, 5, 9, 7, 6, 4, 12, 5, 4, 2, 64, 5, 6, 4, 2, 3, 54, 45, 4, 44] # 原始乱序 29 d0_out = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 9, 12, 15, 44, 45, 54, 64] # 正确排序 30 d1 = quick_sort(d0) 31 print(d1) 32 print(d0_out)