【八大排序算法Python实现】插入排序:直接插入排序、希尔排序

目录

一、直接插入排序

算法思想:

算法稳定性

 Python代码

二、二分查找优化直接插入排序

 Python代码

三、希尔排序

算法思想:

算法稳定性

 Python代码


此次博客中的直接插入排序(及二分优化版直接插入排序)、希尔排序都是属于插入排序。博客代码是博主想复习下排序算法然后手打的,已经过调试。若还有错误请指出!

 

一、直接插入排序

 

算法思想:

假设有一组无序序列 R0, R1, ... , RN-1。

(1) 我们先将这个序列中下标为 0 的元素视为元素个数为 1 的有序序列。

(2) 然后,我们要依次把 R1, R2, ... , RN-1 插入到这个有序序列中。所以,我们需要一个外部循环,从下标 1 扫描到 N-1 。

(3) 接下来描述插入过程。假设这是要将 Ri 插入到前面有序的序列中。由前面所述,我们可知,插入Ri时,前 i-1 个数肯定已经是有序了。

所以我们需要将Ri 和R0 ~ Ri-1 进行比较,确定要插入的合适位置。这就需要一个内部循环,我们一般是从后往前比较,即从下标 i-1 开始向 0 进行扫描

当数据正序时,执行效率最好,每次插入都不用移动前面的元素,时间复杂度为O(N)。
当数据反序时,执行效率最差,每次插入都要前面的元素后移,时间复杂度为O(N^2)。
所以,数据越接近正序,直接插入排序的算法性能越好
平均             最坏     最好     空间        稳定性     复杂性
O(n²)  O(n²)  O(n)   O(1)     稳定       简单

 

算法稳定性

直接插入排序的过程中,不需要改变相等数值元素的位置,所以它是稳定的算法。

 

 

 Python代码

# 直接插入排序
def insert_sort(input_list):
    if len(input_list) <= 1:
        return input_list
    for i in range(len(input_list)):
        j = i - 1
        while j >= 0 and input_list[j] > input_list[j+1]:
            input_list[j],input_list[j+1] = input_list[j+1],input_list[j]
            j -= 1
    return input_list

 

二、二分查找优化直接插入排序

因为在一个有序序列中查找一个插入位置,以保证有序序列的序列不变,所以可以使用二分查找,减少元素比较次数提高效率。

 

 Python代码

  • 二分查找递归版
# 递归二分查找 有指针
def binary_search2(input_list, num, left, right):
    if left > right:
        return left if left < len(input_list) else -1 # 若所找的数大于数组所有数则会返回-1,即放在最后,其他情况返回left即可
    middle = (left + right) // 2
    if num > input_list[middle]:
        left = middle + 1
    elif num < input_list[middle]:
        right = middle - 1
    else:
        return middle
    return binary_search2(input_list,num,left, right)
  • 二分查找非递归版
# 无递归二分查找 有指针
def binary_search1(input_list,num):
    '''
    :param num:
    :param input_list: 有序列表
    :return: 所找数字的索引
    '''
    # 每次二分 直到最后一次才找到 就会有 2^k = n / 2 得到 k = long2n + 1
    # 如果找不存在数组里的要return left,否则返回-1
    # 二叉树查找的思想是二分查找,查找的次数(效率)取决于二叉树的高度。
    left = 0
    right = len(input_list) - 1
    while left <= right:
        middle = (left + right) // 2
        if num == input_list[middle]:
            return middle
        elif num > input_list[middle]:
            left = middle + 1
        else:
            right = middle - 1
    return left if left < len(input_list) else -1 # 若所找的数大于数组所有数则会返回-1,即放在最后,其他情况返回left即可
  • 二分查找直接插入排序
# 直接排序优化:利用二分搜索查找索引加快速度
def binary_insert_sort(input_list):
    if len(input_list) <= 1:
        return input_list
    for i in range(1,len(input_list)):
        j = i - 1
        search_index = binary_search1(input_list[:i+1],input_list[i])
        if search_index != -1:
            while j >= search_index:
                input_list[j],input_list[j+1] = input_list[j+1],input_list[j]
                j -= 1
        else: # 若是-1,说明input_list[i]比它之前的数都大,所以不用改变位置
            break
    return input_list

三、希尔排序

 

算法思想:


希尔排序:缩小增量排序
增量:等于组数,等于每组元素相隔距离
步长序列的不同,会导致最坏的时间复杂度情况的不同。
以N/2为步长的最坏时间复杂度为N^2。用这样步长序列的希尔排序比插入排序要快,甚至在小数组中比快速排序和堆排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。

 

直接插入排序更适合于原始记录基本有序的集合。
希尔排序的比较次数和移动次数都要比直接插入排序少,当N越大时,效果越明显。
直接插入排序也适用于链式存储结构;希尔排序不适用于链式结构。
  平均        最坏     最好     空间     稳定性     复杂性
O(nlogn)  O(n²)    O(n)  O(1)     不稳定     较复杂
 

 

算法稳定性

希尔排序中相等数据可能会交换位置,所以希尔排序是不稳定的算法。

 

 Python代码

def shell_sort(input_list):
    if len(input_list) <= 1:
        return input_list
    gap = len(input_list) // 2
    while gap >= 1:
        for i in range(gap,len(input_list)):
            j = i -gap
            while j >= 0 and input_list[j] > input_list[j+gap]:
                input_list[j],input_list[j+gap] = input_list[j+gap],input_list[j]
                j -= gap
        gap //= 2
    return input_list
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值