华电北风吹
天津大学认知计算与应用重点实验室
最后修改日期:2015/8/22
声明:本文涉及的所有排序算法定义功能对输入进行从小到大排序
符号解释:
n:输入数据个数
Θ(n):n的同阶无穷大
一、选择排序
def SelectSort(a): for i in range(0,len(a)-1): minIndex=i for j in range(i+1,len(a)): if a[j]<a[minIndex]: minIndex=j if minIndex !=i: temp=a[minIndex] a[minIndex]=a[i] a[i]=temp return a a=[2,5,3,8,6,1,4,9] SelectSort (a) print(a)从前往后,依次选择当前位置以后最小的数与当前位置交换
计算复杂度theta(n^2)
二、冒泡排序
def BubbleSort (a): k=len(a) for i in range(0,k-1): for j in range(k-1,i,-1): if a[j]<a[j-1]: a[j-1],a[j]=a[j],a[j-1] return a a=[2,5,3,8,6,7,1,4,9] BubbleSort (a) print(a)
从前往后,反复交换相邻的未按次序排列的元素
计算复杂度theta(n^2)
三、插入排序
def InsertSort(a): for j in range(1,len(a)): key=a[j] i=j-1 while(i>=0 and a[i]>key): a[i+1]=a[i] i=i-1 a[i+1]=key a=[2,5,3,8,6,1,4,9] InsertSort (a) print(a)
从前往后,讲下一个数据插入到前面已经排好序的数组里面
最好的情况:已经从小到大排好序,计算复杂度theta(n)
最坏的情况:输入顺序为从大到小,计算复杂度theta(n^2)
当数据量很大的时候,不必要一个一个往前找,可以根据二分发,减少计算量
四、归并排序
def MergeSort(a): n=len(a) if n==1: return a mid=(n+1)//2 b=MergeSort(a[0:mid]) c=MergeSort(a[mid:n]) i=0 j=0 b.append(float("inf")) c.append(float("inf")) for k in range(0,n): if b[i]<c[j]: a[k]=b[i] i+=1 else: a[k]=c[j] j+=1 return a a=[2,5,3,8,6,7,1,4,9] MergeSort (a) print(a)
分治策略,先划分子序列,后归并排序
计算复杂度theta(nlog(n))
注意:非原址运算
五、堆排序
def HeapAdjust(lst,k,n): while(2*k+1<n): j=2*k+1 if j+1<n and lst[j]<lst[j+1]: j=j+1 if lst[j]>lst[k]: lst[k],lst[j]=lst[j],lst[k] k=j else: break return lst def HeapSort(lst): n=len(lst) for i in range(n//2-1,-1,-1): lst=HeapAdjust(lst,i,n) for i in range(n-1,0,-1): lst[0],lst[i]=lst[i],lst[0] lst=HeapAdjust(lst,0,i) return lst a=[1,5,2,8,3,4,6,9,7] HeapSort(a) print(a)
代码注释:http://blog.csdn.net/zhangzhengyi03539/article/details/44889951
构建大根堆,然后堆顶元素与序列最后一个元素交换,序列长度减一,对堆顶元素构建大根堆
计算复杂度theta(nlogn)
我觉得这个算法还有可能改进的地方,因为每次堆顶元素与最后一个元素交换,而最后一个元素是大根堆叶子上的元素,也就是在这条支路中最小的元素,这样在重新对堆顶元素构建大根队的过程中需要迭代好多步骤。
六、快速排序
例子一:
def QuickSort(a,start,end): key=a[start] i=start+1 j=end while i<j: while a[i]<=key and i<j: i+=1 while a[j]>key and j>i-1: j-=1 if i<j: a[i],a[j]=a[j],a[i] a[start],a[j]=a[j],a[start] if j-1>start: QuickSort(a,start,j-1) if j+1<end: QuickSort(a,j+1,end) return a a=[1,5,2,8,3,4,6,9,7] QuickSort(a,0,len(a)-1) print(a)
例子二:
def QuickSort(a,start,end): key=a[end] i=start-1 for j in range(start,end): if a[j]<key: i+=1 a[i],a[j]=a[j],a[i] a[i+1],a[end]=a[end],a[i+1] if i>start: QuickSort(a,start,i) if i+2<end: QuickSort(a,i+2,end) return a a=[1,5,2,8,3,4,6,9,7] QuickSort(a,0,len(a)-1) print(a)
分治策略,最好的情况当然是每次都是二分了
平均情况/期望情况:计算复杂度theta(nlogn)
最坏的情况:计算复杂度theta(n^2)
对于例子二,考虑这样一种情况,输入序列最后一个是最大的,然后对j循环的时候每次都要执行交换操作。还有就是快速排序的随机化版本,每次从输入中随机挑选一个数与key所在的数交换,然后执行快速排序。