排序 3 - 折半插入排序

10 篇文章 0 订阅
10 篇文章 0 订阅

参考:

排序 0 - 前言

百度百科:折半插入排序

百度百科:二分法插入排序


折半插入排序(binary insert sort)

工作原理

对插入排序算法的改进,针对已排序序列,利用 二分法 进行数据查找,将待排序数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据。

算法思想

设待排序序列大小为 n,共遍历 n-1 次,i 表示当前遍历的次数,也表示已排序序列的终止位置和待排序序列的起始位置。设置已排序序列开始和末尾下标为 lowhigh,其中中间位置数据的下标为 m = (low+high)/2。将待排序数据和中间位置数据进行比较,如果中间位置数据 小于等于(或者大于等于) 待排序数据,则设置 low = m+1;否则 high = m-1,然后继续计算中间下标 m,进行比较,直到满足条件 low > high 为止,将待排序数据插入到 hight+1 的位置


Python 算法实现

# -*- coding: utf-8 -*-

"""
二分插入排序,又称折半插入排序
"""

import random


def create_data(leng, min, max):
    """
    创建待排序序列
    :param leng: 序列长度
    :param min: 最小值
    :param max: 最大值
    :return: 列表
    """
    li = range(min, max)
    return random.sample(li, leng)


def binary_insert_sort(li, reverse=False):
    """
    二分插入排序实现
    :param li: 待排序列表
    :param reverse: 是否从大到小排序,默认为False
    :return: 已排序列表
    """
    for i in xrange(1, len(li)):
        low = 0
        high = i - 1
        while low <= high:
            m = (low + high) / 2
            if li[m] <= li[i]:
                if reverse:
                    high = m - 1
                else:
                    low = m + 1
            else:
                if reverse:
                    low = m + 1
                else:
                    high = m - 1
        li.insert(high + 1, li[i])
        del li[i + 1]

    return li


if __name__ == '__main__':
    da = create_data(10, 30, 60)
    print da
    binary_insert_sort(da, True)
    print da

性能分析

稳定性

折半插入排序是稳定排序算法

折半插入排序是对插入排序算法的改进,重点变化在于待排序数据的比较过程。

但是,在实际编程中,同样有可能使折半插入排序成为 不稳定的排序算法,下面介绍不稳定的排序算法过程

假设有如下待排序序列:(3,0),(2,1),(3,2),实现从小到大的排序

  • 第一次排序,已排序序列为 (3,0),所以 low = high = 0 -> m = 0,待排序数据 (2,1) 比中间位置数据 (3,0) 小,所以 high = m-1 = -1,满足 low > high 的条件,结束排序,将 (2,1) 插入到 high+1 = 0 的位置

得到结果:(2,1),(3,0),(3,2)

  • 第二次排序,已排序序列为 (2,1),(3,0),所以 low = 0, high = 1, m = 0,待排序数据为 (3,2)

第一次比较,(2,1) 小于 (3,2),所以 low = m+1 = 1, m = (low + high) / 2 = 1

第二次比较,(3,0) 大于等于 (3,2),所以 high = m-1 = 0,所以 low > high,将 (3,2) 插入到 high+1 = 1 的位置上

得到结果:(2,1),(3,2),(3,0),是不稳定的排序结果

所以,在比较时,当中间数据 大于等于(或者小于等于)待排序数据时,选择右边已排序序列继续操作,才能保证是稳定的

时间复杂度

折半插入排序改变了插入排序算法的比较次数,未改变其待排序数据移动次数

最好情况下,插入的位置,刚好是二分位置,时间复杂度为 O(nlogn)

最坏情况下,时间复杂度为 O(n^2)

平均时间复杂度为 O(n^2)

空间复杂度

空间复杂度为 O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值