最近在找工作面试的时候总是会被问到排序算法的种种,现在对排序算法进行一个系统的总结。也算是再复习一遍的,有好多自己也忘得差不多了。
排序有内部排序和外部排序两大类。内部排序值得是所有的排序是在内存中进行;外部排序则是因为数据量太大,一次不能将全部数据放在内存中,在排序过程中,需要访问外存。
关于时间复杂度和空间复杂度
由于时间关系,我没有自己画,以下的表格是在别处转的,详见常用排序算法总结
1.插入排序--直接插入排序(Straight Insertion Sort)
基本思想:
将一个记录插入到已经有序的表中,从而得到一个新的,记录数+1的有序表。即:先将序列的第一个记录看成是一个有序的子序列,然后从第二个记录逐个进行插入,直至整个序列有序为止。
如果遇到元素相等时,那么将插入的元素插入到与其相等的元素之后。相等元素的前后顺序并没有改变,所以插入排序是稳定的。
算法的实现:
def insertion_sort(arr): arrlen = len(arr) for i in range(1, arrlen): insert(arr, i) def insert(arr, i): tmp = arr[i] j = i # 查找第i的元素应该的位置, 并且 # 顺便把比它大的元素往后挪 # 其实是用了心思在里面的 while j > 0 and tmp < arr[j - 1]: arr[j] = arr[j - 1] j -= 1 arr[j] = tmp a = [65,6,3,5,54,65] insertion_sort(a) print a
2.希尔排序
基本思想:
希尔排序又叫做缩小增量排序。先将整个序列分割成若干个子序列,并对每个子序列进行直接插入排序,再对全部序列进行直接插入排序。
算法实现:
def shell_sort(seq): incr = len(seq)/2 while(incr>=1): for i in range(incr,len(seq)): tmp=seq[i] pos=i; for j in range(i-incr,-1,-incr): if seq[j]>tmp: seq[j+incr]=seq[j] pos=j seq[pos]=tmp incr = incr/2 return seq if __name__ == ‘__main__‘: A = [10, -3, 5, 7, 1, 3, 7] print ‘Before sort:‘,A shell_sort(A) print ‘After sort:‘,A
3.选择排序--简单选择排序
基本思想:
在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
算法实现:
def selectionSort(seq): length=len(seq) for i in range(length): mini=min(seq[i:]) if seq[i]>mini: j=seq.index(mini,i) seq[i],seq[j]=seq[j],seq[i] if __name__==‘__main__‘: seq=[3,4,5,9,3,1,5,7,90,-2,] selectionSort(seq) print(seq)
效率:
最坏情况下,即待排序记录初始状态是按第一条记录最大,之后的记录从小到大顺序排列,则需要移动记录的次数最多为3(n-1)。简单选择排序过程中需要进行的比较次数与初始状态下待排序的记录序列的排列情况无关。当i=1时,需进行n-1次比较;当i=2时,需进行n-2次比较;依次类推,共需要进行的比较次数是(n-1)+(n-2)+…+2+1=n(n-1)/2,即进行比较操作的时间复杂度为O(n^2),进行移动操作的时间复杂度为O(n)。(百度百科)
简单选择排序是不稳定排序。