排序 2 - 插入排序

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

参考:

排序 0 - 前言

百度百科:插入排序


插入排序(insert sort)

工作原理

将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据。

算法思想

设待排序序列大小为 n,从头到尾共遍历 n-1 次,i 表示当前遍历的次数,也表示已排序序列的终止位置和待排序序列的起始位置,获取下标为 i 的值在已排序序列中的位置,将该值移动到该位置


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 insert_sort_v1(li, reverse=False):
    """
    稳定的插入排序实现,将待排序数据插入到已排序序列中时,从右到左开始查找
    :param li: 待排序列表
    :param reverse: 是否从大到小排序,默认为False
    :return: 已排序列表
    """
    for i in xrange(1, len(li)):
        k = i
        for j in range(i)[::-1]:
            if reverse:
                if li[i] <= li[j]:
                    k = j + 1
                    break
                else:
                    k = j
            else:
                if li[i] >= li[j]:
                    k = j + 1
                    break
                else:
                    k = j
        li.insert(k, li[i])
        del li[i + 1]

    return li


def insert_sort_v2(li, reverse=False):
    """
    不稳定的插入排序实现,将待排序数据插入到已排序序列中时,从左到右开始查找
    :param li: 待排序列表
    :param reverse: 是否从大到小排序,默认为False
    :return: 已排序列表
    """
    for i in xrange(1, len(li)):
        k = i
        for j in xrange(i):
            if reverse:
                if li[i] >= li[j]:
                    k = j
                    break
            else:
                if li[i] <= li[j]:
                    k = j
                    break
        li.insert(k, li[i])
        del li[i + 1]

    return li


def insert_sort(li, reverse=True, way=1):
    """
    插入排序
    :param li: 待排序列表
    :param reverse:是否从大到小排序,默认为False
    :param way: 1 表示使用方法 insert_sort_v1;2表示使用方法 insert_sort_v2
    :return:已排序列表
    """
    if way == 1:
        return insert_sort_v1(li, reverse)
    elif way == 2:
        return insert_sort_v2(li, reverse)


if __name__ == '__main__':
    da = create_data(10, 30, 60)
    print da
    insert_sort(da, way=2)
    print da

性能分析

稳定性

插入排序是稳定排序算法

资料上说插入排序是稳定的排序算法,也就是相同值的相对位置在排序过后会保持不变,不过个人实际编程后觉得判断插入排序是否稳定和实际实现的算法很有关系

如上节算法实现中所示,将待排序数据插入到已排序序列中时,有两种插入方法:

  • 选择从右往左进行比较,如果下标为 i 的数据小于等于(或者大于等于)待排序数据,将待排序数据插入到下标为 i+1 的位置上。这是 稳定 的插入排序算法
  • 选择从左往右进行比较,如果下标为 i 的数据小于等于(或者大于等于)待排序数据,将待排序数据插入到下标为 i 的位置上,这是 不稳定 的插入排序算法

比如待排序序列为 (4,0),(4,1),(2,2)

  • 按照第一种插入方法

插入排序后,已排序序列为为 (2,2),(4,0),(4,1)

那么该插入排序算法是稳定的

  • 按照第二种插入方法

插入排序后,已排序序列为 (2,2),(4,1),(4,0)

那么值为 4 的两个元素的相对位置在排序完成后发生了变化,该插入排序算法是不稳定算法

时间复杂度

基本操作为

...
    k = i
    ...
                k = j
                break
        ...
                k = j
                break
    li.insert(k, li[i])
    del li[i + 1]

return li

最好情况下,直接在已排序序列的首位(或者末位)插入,那么时间复杂度为 O(n)

最坏情况下,每次插入到已排序序列的末尾,那么时间复杂度为 O(n^2)

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

空间复杂度

仅使用了变量 k,所以空间复杂度为 O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值