算法导论—排序算法总结(python)

华电北风吹

天津大学认知计算与应用重点实验室

最后修改日期: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所在的数交换,然后执行快速排序。

你可能感兴趣的:(算法,python,排序算法)