wuxiaosi0 2020-01-08
十种常见排序算法可以分为两大类:
基础定义
图示
为了防止误导读者,本文所有概念性内容均截取自对应Wiki。
原理
冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
步骤
冒泡排序算法的运作如下:
代码
def bubble_sort(list): length = len(list) # 第一级遍历 for index in range(length): # 第二级遍历 for j in range(1, length - index): if list[j - 1] > list[j]: # 交换两者数据,这里没用temp是因为python 特性元组。 list[j - 1], list[j] = list[j], list[j - 1] return list
这种排序其实还可以稍微优化一下,添加一个标记,在排序已完成时,停止排序。
def bubble_sort_flag(list): length = len(list) for index in range(length): # 标志位 flag = True for j in range(1, length - index): if list[j - 1] > list[j]: list[j - 1], list[j] = list[j], list[j - 1] flag = False if flag: # 没有发生交换,直接返回list return list return list
原理
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理大致是将后面的元素最小元素一个个取出然后按顺序放置。
步骤
代码
def selection_sort(list): n=len(list) for i in range (0,n): min = i for j in range(i+1,n): if list[j]<list[min]: min=j list[min],list[i]=list[i],list[min] return list
原理
插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
步骤
代码
def insert_sort(list): n = len(list) for i in range(1, n): # 后一个元素和前一个元素比较 # 如果比前一个小 if list[i] < list[i - 1]: # 将这个数取出 temp = list[i] # 保存下标 index = i # 从后往前依次比较每个元素 for j in range(i - 1, -1, -1): # 和比取出元素大的元素交换 if list[j] > temp: list[j + 1] = list[j] index = j else: break # 插入元素 list[index] = temp return list
原理
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率
但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
步骤
每次以一定步长(就是跳过等距的数)进行排序,直至步长为1.
代码
def shell_sort(list): n = len(list) # 初始步长 gap = n // 2 while gap > 0: for i in range(gap, n): # 每个步长进行插入排序 temp = list[i] j = i # 插入排序 while j >= gap and list[j - gap] > temp: list[j] = list[j - gap] j -= gap list[j] = temp # 得到新的步长 gap = gap // 2 return list
步长使用的是Donald Shell的建议,另外步长还可以使用Sedgewick提出的(1, 5, 19, 41, 109,…)。
也可以使用斐波那契数列除去0和1将剩余的数以黄金分区比的两倍的幂进行运算得到的数列。
原理
归并操作(归并算法),指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。
步骤
1.迭代法
递归法
假设序列共有n个元素:
代码
# 递归法 def merge_sort(list): # 认为长度不大于1的数列是有序的 if len(list) <= 1: return list # 二分列表 middle = len(list) // 2 left = merge_sort(list[:middle]) right = merge_sort(list[middle:]) # 最后一次合并 return merge(left, right) # 合并 def merge(left, right): l,r=0,0 result=[] while l<len(left) and r<len(right): if left[l] <right[r]: result.append(left[l]) l+=1 else: result.append(right[r]) r +=1 reslut +=left[l:] result+=right[r:] return result
鄙人不才,不知归并排序的迭代法如何用Python实现,望指教。
原理
快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。
步骤
代码
普通版
def quick_sort(list): less = [] pivotList = [] more = [] # 递归出口 if len(list) <= 1: return list else: # 将第一个值做为基准 pivot = list[0] for i in list: # 将比急转小的值放到less数列 if i < pivot: less.append(i) # 将比基准打的值放到more数列 elif i > pivot: more.append(i) # 将和基准相同的值保存在基准数列 else: pivotList.append(i) # 对less数列和more数列继续进行排序 less = quick_sort(less) more = quick_sort(more) return less + pivotList + more
咳咳,下面这段代码出自《Python cookbook 第二版》传说中的三行实现python快速排序。
def qsort(arr): if len(arr) <= 1: return arr else: pivot = arr[0] less = [x for x in arr[1:] if x < pivot] greater = [x for x in arr[1:] if x >= pivot] return qsort(less) + [pivot] + qsort(greater)
当然还有一行语法糖版本:
qs = lambda xs : ( (len(xs) <= 1 and [xs]) or [ qs( [x for x in xs[1:] if x < xs[0]] ) + [xs[0]] + qs( [x for x in xs[1:] if x >= xs[0]] ) ] )[0]
是不是感受到了Python的魅力?
原理
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
步骤
代码
def heap_sort(list): # 创建最大堆 for start in range((len(list) - 2) // 2, -1, -1): sift_down(list, start, len(list) - 1) # 堆排序 for end in range(len(list) - 1, 0, -1): list[0], list[end] = list[end], list[0] sift_down(list, 0, end - 1) return list # 最大堆调整 def sift_down(lst, start, end): root = start while True: child = 2 * root + 1 if child > end: break if child + 1 <= end and lst[child] < lst[child + 1]: child += 1 if lst[root] < lst[child]: lst[root], lst[child] = lst[child], lst[root] root = child else: break
原理
当输入的元素是n个0到k之间的整数时,它的运行时间是Θ(n + k)。计数排序不是比较排序,排序的速度快于任何比较排序算法。
由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要大量时间和内存。例如:计数排序是用来排序0到100之间的数字的最好的算法,但是它不适合按字母顺序排序人名。但是,计数排序可以用在基数排序算法中,能够更有效的排序数据范围很大的数组。
步骤
代码
def count_sort(list): min = 2147483647 max = 0 # 取得最大值和最小值 for x in list: if x < min: min = x if x > max: max = x # 创建数组C count = [0] * (max - min +1) for index in list: count[index - min] += 1 index = 0 # 填值 for a in range(max - min+1): for c in range(count[a]): list[index] = a + min index += 1 return list
None?
当然不会
自然就是系统自带的
list.sort()