排序(1) 初级排序

插入排序之直接插入排序

基本思想:每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中的适当位置上,使得插入后依然有序,直到全部插入完为止。

直接插入排序的Python实现如下:

def InsertionSort(A,first,last):
    for i in range(first+1,last+1):
        key = A[i]
        j = i-1
        while j>=first and A[j]>key:
            A[j+1] = A[j]
            j -= 1
        A[j+1] = key

为了便于理解,图示说明执行过程。

这里引用算法导论里的插图,上图清楚的展示了插入排序的过程。这里需要注意的是,上图数组下标从1开始,而代码里遵从语言设计,数组下标从0开始。如果觉得上图的这个过程还不够形象深刻,推荐大家一个直观学习算法和数据结构的网站:http://zh.visualgo.net

评价:插入排序是稳定的、原址的,待排序记录少的时候性能不错,原始数组基本有序的情况下渐进时间复杂度为O(n),平均情况(原始数组随机排列)和最坏情况(逆序)下,渐进时间复杂度为O(n^2)

改进与拓展:二分插入排序(减少比较次数)、链表插入排序(减少移动次数)、希尔排序(缩小增量排序)

这里要简单说说希尔排序,希尔排序是直接插入排序的改进。一方面,当数组基本有序时直接插入时间复杂度可就提高至O(n)。另一方面,直接插入排序算法简单,待排序记录少时效率也比较高。希尔排序是利用以上两点对其改进的算法。它的基本思想是:先将整个排序记录分割成若干子序列(如何分割?按照某个‘增量’间隔的记录组成一个子序列,每排完一趟,减少‘增量’,直到‘增量’为1)分别进行直接插入排序,待整个数组基本有序时,再对全体记录进行一次直接插入排序。

下面是希尔排序过程图:
这里写图片描述
图中相同颜色的记录构成一个子序列,这里的增量取5,3,1。

希尔排序的Python代码实现如下:

#T = O(n^k) 其中1<k<2,根据不同的增量序列k值在范围内有不同,
def ShellSort(A,first,last):
    increment = (last - first + 1)>>1 #增量递减速度
    while increment :
        for i in range(first,first + increment):
            for j in range(i,last+1,increment):
                key = A[j]
                k = j-increment
                while k>=i and A[k]>key:
                    A[k+increment] = A[k]
                    k -= increment
                A[k+increment] = key
        increment >>= 1 

实际中,增量序列可有多种取法,如塞克威奇的《算法第四版》用了…40,13,4,1。其他有取…9,5,3,2,1 等等。具体效果如何,不如大家在实际测试后再选择。
希尔排序是不稳定的,原址的,平均情况下时间复杂度O(n^1.3)。


选择排序之简单选择排序

基本思想:从所有待排序列中找到最小的元素,然后与第一个位置的元素交换。之后再从剩余元素中找到最小元素,与第二个位置的元素交换……以此类推直到整个序列有序。

简单选择排序的Python实现如下:

#从数组A的第first到第last个元素中找到最小元素,并返回对应的下标
def FindMin(A,first,last):
    minElemPos = first
    for i in range(first+1,last+1):
        if A[i] < A[minElemPos]:
            minElemPos = i
    return minElemPos   

def SelectionSort(A,first,last):
    for i in range(first, last):
        minElemPos = FindMin(A,i,last)
        A[i],A[minElemPos] = A[minElemPos],A[i]

执行的过程可以描述如下:

图1.2 选择排序过程图

评价:简单选择排序是原址的、不稳定的,任何情况下算法的渐进时间复杂度都是O(n^2)

改进与拓展:树形选择排序、堆排序


交换排序之冒泡排序

基本思想:依次比较相邻的两个数,将小数放在前面,大数放在后面。比如第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。

冒泡算法的Python实现(这里用冒泡的上浮法实现,与冒泡的下沉法原理是一样的,只不过遍历数组方向不一样):

#python3.3
#T = O(n^2)
def BubbleSort(A,first,last):
    for i in range(first,last):
        for j in range(last,i,-1):
            if A[j] < A[j-1]:
                A[j],A[j-1] = A[j-1],A[j]

基本过程可以描述如下:

图1.3 冒泡排序过程图

评价:冒泡排序是稳定的、原址的,基本思想和实现简单,最好情况渐进时间复杂度为O(n),最坏和平均情况为O(n^2)。

改进和拓展快速排序

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值