上期为你们讲解了排序算法常见的几个概念:html
若是有遗忘的同窗能够看排序算法——(1)简介这篇文章复习一下。python
今天将为你们介绍经常使用的十大排序算法中最简单的五种(冒泡、选择、插入、希尔、归并),主要从:过程图解、算法思想、代码实现、算法分析这四个方面讲解,建议你们看完以后本身动手练习增强记忆!
注:本文使用的复杂度均为最坏复杂度算法
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的元素列,依次比较两个相邻的元素,一层一层的将较大的元素日后移动,其现象和睦泡在上升过程当中慢慢变大相似,故成为冒泡排序。shell
def bubble_sort(arr): """冒泡排序""" # 第一层for表示循环的遍数 for i in range(len(arr) - 1): # 第二层for表示具体比较哪两个元素 for j in range(len(arr) - 1 - i): if arr[j] > arr[j + 1]: # 若是前面的大于后面的,则交换这两个元素的位置 arr[j], arr[j + 1] = arr[j + 1], arr[j] return arr
冒泡排序是一种简单直接暴力的排序算法,为何说它暴力?由于每一轮比较可能多个元素移动位置,而元素位置的互换是须要消耗资源的,因此这是一种偏慢的排序算法,仅适用于对于含有较少元素的数列进行排序。数组
选择排序(Selection sort)是一种简单直观的排序算法。它的工做原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,因此称为:选择排序app
def selection_sort(arr): """选择排序""" # 第一层for表示循环选择的遍数 for i in range(len(arr) - 1): # 将起始元素设为最小元素 min_index = i # 第二层for表示最小元素和后面的元素逐个比较 for j in range(i + 1, len(arr)): if arr[j] < arr[min_index]: # 若是当前元素比最小元素小,则把当前元素角标记为最小元素角标 min_index = j # 查找一遍后将最小元素与起始元素互换 arr[min_index], arr[i] = arr[i], arr[min_index] return arr
选择排序和冒泡排序很相似,可是选择排序每轮比较只会有一次交换,而冒泡排序会有屡次交换,交换次数比冒泡排序少,就减小cpu的消耗,因此在数据量小的时候能够用选择排序,实际适用的场合很是少。ide
插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工做原理是经过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。函数
def insertion_sort(arr): """插入排序""" # 第一层for表示循环插入的遍数 for i in range(1, len(arr)): # 设置当前须要插入的元素 current = arr[i] # 与当前元素比较的比较元素 pre_index = i - 1 while pre_index >= 0 and arr[pre_index] > current: # 当比较元素大于当前元素则把比较元素后移 arr[pre_index + 1] = arr[pre_index] # 往前选择下一个比较元素 pre_index -= 1 # 当比较元素小于当前元素,则将当前元素插入在 其后面 arr[pre_index + 1] = current return arr
插入排序的适用场景:一个新元素须要插入到一组已是有序的数组中,或者是一组基本有序的数组排序。ui
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量(间隔)排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本,它与插入排序的不一样之处在于,它会优先比较距离较远的元素,该方法因D.L.Shell于1959年提出而得名。spa
希尔排序的总体思想是将固定间隔的几个元素之间排序,而后再缩小这个间隔。这样到最后数列就成为了基本有序数列,而前面咱们讲过插入排序对基本有序数列排序效果较好。
已知的最增量式是由 Sedgewick 提出的 (1, 5, 19, 41, 109,…),该步长的项来自 9 * 4^i - 9 * 2^i + 1 和 4^i - 3 * 2^i + 1 这两个算式。这项研究也代表 "比较在希尔排序中是最主要的操做,而不是交换。 用这样增量式的希尔排序比插入排序和堆排序都要快,甚至在小数组中比快速排序还快,可是在涉及大量数据时希尔排序仍是比快速排序慢。
def shell_sort(arr): """希尔排序""" # 取整计算增量(间隔)值 gap = len(arr) // 2 while gap > 0: # 从增量值开始遍历比较 for i in range(gap, len(arr)): j = i current = arr[i] # 元素与他同列的前面的每一个元素比较,若是比前面的小则互换 while j - gap >= 0 and current < arr[j - gap]: arr[j] = arr[j - gap] j -= gap arr[j] = current # 缩小增量(间隔)值 gap //= 2 return arr
归并排序(MERGE-SORT)是创建在归并操做上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个很是典型的应用。归并排序适用于子序列有序的数据排序。
从上图看分解后的数列很像一个二叉树。
def merge_sort(arr): """归并排序""" if len(arr) == 1: return arr # 使用二分法将数列分两个 mid = len(arr) // 2 left = arr[:mid] right = arr[mid:] # 使用递归运算 return marge(merge_sort(left), merge_sort(right)) def marge(left, right): """排序合并两个数列""" result = [] # 两个数列都有值 while len(left) > 0 and len(right) > 0: # 左右两个数列第一个最小放前面 if left[0] <= right[0]: result.append(left.pop(0)) else: result.append(right.pop(0)) # 只有一个数列中还有值,直接添加 result += left result += right return result
今天给你们介绍的五种排序是比较简单的排序,建议你们本身动手敲几遍代码,书读百遍,其义自现。要求你们必须理解&记住它们的算法原理,由于代码是永远记不住的,只要记住原理你就能用伪代码实现。 为了方便你们记忆我在每一个算法分析最后给出了本身的记忆方法,若是你有不理解的地方,欢迎在下方留言,同时也欢迎你们转发分享!