python--数据结构--直接插入类排序、折半插入排序、希尔排序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码实现:

# insert_type_sort
from collections import deque
from typing import List


class Record:
    def __init__(self, key):
        self.key = key
        self.other_info = None


class Records:
    def __init__(self, record_list: List[Record]):
        self.record_list = deque([None])
        self.record_list.extend(record_list)
        self.record_len = len(self.record_list)-1
        self.other_info = None


def insert_sort(records: Records):
    """
    直接插入类排序

    时间复杂度:
        O(n**2)

    空间复杂度:
        O(1)

    最好情况:
        顺序

    最坏情况:
        逆序

    适用情况:
        适用于待排序记录数目较少且基本有序的情况。当待排记录数目较大时,直接插入排序的性能就不好,因此可以
    对直接插入排序做进一步的改进。在直接插入排序法的基础上,从减少“比较关键字”和“移动记录”两种操作的次
    数着手进行改进。

    :param records:
    :return:
    """
    for i in range(2, records.record_len+1):
        records.record_list[0] = records.record_list[i]  # 将待插入记录存放到监视哨records.record_list[0]中
        j = i - 1
        while records.record_list[0].key < records.record_list[j].key:
            records.record_list[j+1] = records.record_list[j]
            j -= 1
        records.record_list[j+1] = records.record_list[0]  # 将待插入记录插入到已排好序的序列中
    return records


def bin_sort(records: Records):
    """
    折半插入排序

    算法思想:
            从关于查找的讨论中可知,对于有序表进行折半查找,其性能由于顺序查找。所以,可以将折半查找思想用于在有序记录
        r[1...i-1]中确定应插入位置,相应的排序法称为折半插入排序法。

    算法分析:
            采用折半插入排序法,可减少关键字的比较次数。每插入一个元素,需要比较的次数最大未折半判定树的深度,如插入第
        i个元素时,设i=2**j,则需进行log₂i次比较,因此插入n-1个元素的平均关键字的比较次数为nlog₂n。当n比较大时,折半插
        入排序法的比较次数比直接插入排序的最差情况要好很多,但比其最好情况要差。
            虽然折半插入排序与直接插入排序法相比较,改善了算法中比较次数的数量级,达到O(nlog₂n),但其并未改变移动元素
        的时间耗费,所以折半插入排序的总的时间复杂度为O(n**2)。


    :param records: 未排好序的records对象
    :return: 排序序的记录records对象
    """
    for i in range(2, records.record_len+1):
        x = records.record_list[i]
        low = 1
        high = i - 1
        while low <= high:
            # 只有low大于high时循环才会终止,
            # 当low=high时,恰好x.key >= records.record_list[mid].key,退出循环后low为需要开始移动的元素开始位置
            mid = (low + high)//2
            if x.key < records.record_list[mid].key:
                high = mid - 1
            else:
                low = mid + 1
        for j in range(i-1, low-1, -1):
            # low位置的元素也需要移动,low的前一个位置也就是high位置的元素的关键字恰好小于等于x的关键字
            records.record_list[j+1] = records.record_list[j]
        records.record_list[low] = x
    return records


def shell_insert(records: Records, delta):
    """
    对记录数组records.record_list做一趟希尔插入排序,records.record_len为数组长度,delta为增量

    过程类似于直接插入类排序

    """
    for i in range(1+delta, records.record_len+1):  # 1+delta为第一个子序列的第二个元素下标
        if records.record_list[i].key < records.record_list[i-delta].key:
            records.record_list[0] = records.record_list[i]  # 备份records.record_list[i](不做监视哨)
            j = i-delta
            while j > 0 and records.record_list[0].key < records.record_list[j].key:
                records.record_list[j+delta] = records.record_list[j]
                j -= delta
            records.record_list[j+delta] = records.record_list[0]


def shell_sort(records: Records, deltas: List[int]):
    """
    对记录数组records.record_list做希尔排序,length为数组长度,deltas为增量数组
    :param records: 待排序的记录数组对象
    :param deltas: 增量数组
    :return: 排好序的记录数组对象
    """
    for delta in deltas:
        shell_insert(records, delta)
    return records
# test_insert_type_sort.py
from insert_type_sort import Record, Records, insert_sort, bin_sort, shell_sort


records = Records([Record(key) for key in [48, 62, 39, 77, 55, 14, 35, 98]])
records = insert_sort(records)
print([record.key for record in records.record_list if record])
records = bin_sort(records)
print([record.key for record in records.record_list if record])
records = shell_sort(records, [4, 2, 1])
print([record.key for record in records.record_list if record])


"""
运行结果:
[98, 14, 35, 39, 48, 55, 62, 77, 98]
[14, 35, 39, 48, 55, 62, 77, 98]
[55, 14, 35, 39, 48, 55, 62, 77, 98]

Process finished with exit code 0
"""

[引用《数据结构–用C语言描述 耿国华版》]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值