代码实现:
# 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语言描述 耿国华版》]