python插入排序、希尔排序、快速排序、归并排序

插⼊排序

插⼊排序(英语:Insertion Sort)是⼀种简单直观的排序算法。它的⼯作原
理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,
找到相应位置并插⼊。插⼊排序在实现上,在从后向前扫描过程中,需要反
复把已排序元素逐步向后挪位,为最新元素提供插⼊空间。

时间复杂度

最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
最坏时间复杂度:O(n )
稳定性:稳定

def insertion(li):
    # 插入排序
    n = len(li)  # 
    for i in range(1,n):  # 从索引1开始到n-1 因为range前包含后不包含所以就是列表长度n
        for j in range(i,0,-1):   # 从索引i开始到索引0位置,每次向前一步
            if li[j] < li[j-1]:   # 比较j 和 j前面的一位   如果j小于j-1 换位置   否则不变
                li[j-1],li[j] = li[j],li[j-1]
            else:
                break
li = [17, 26, 93, 54, 77, 31, 44, 55, 20]
insertion(li)
print(li)
# 运行结果是:

[17,20,26,31,44,54,55,77,93]

希尔排序

将上述四⾏数字,依序接在⼀起时我们得到:[ 10 14 73 25 23 13 27 94 33
39 25 59 94 65 82 45 ]。这时10已经移⾄正确位置了,然后再以3为步⻓进
⾏排序

时间复杂度

最优时间复杂度:根据步⻓序列的不同⽽不同
最坏时间复杂度:O(n )
稳定性:不稳定
def shell_sort(li):
“”“希尔排序”""
n = len(li)
gep = n // 2
while gep >= 1: # 如果gep大于等于1式子成立进入循环
for i in range(gep,n) # 遍历gep到最后
j = i
while (j-gep) >= 0: # 如果j-gep 大于等于0循环
if li[j] < li[j-gep]: # 如果li[j] 小于li[j-gep]交换位置
li[j],li[j-gep] = li[j-gep],li[j]
j -= gep # j = j-gep
else:
break
gep //= 2 # 缩小gep一半的范围
li = [17, 26, 93, 54, 77, 31, 44, 55, 20]
shell_sort(li)
print(li)

快速排序

快速排序(英语:Quicksort),⼜称划分交换排序(partition-exchange
sort),通过⼀趟排序将要排序的数据分割成独⽴的两部分,其中⼀部分的
所有数据都⽐另外⼀部分的所有数据都要⼩,然后再按此⽅法对这两部分数
据分别进⾏快速排序,整个排序过程可以递归进⾏,以此达到整个数据变成
有序序列。
步骤为:

  1. 从数列中挑出⼀个元素,称为"基准"(pivot),
  2. 重新排序数列,所有元素⽐基准值⼩的摆放在基准前⾯,所有元素⽐基
    准值⼤的摆在基准的后⾯(相同的数可以到任⼀边)。在这个分区结束
    之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursive)把⼩于基准值元素的⼦数列和⼤于基准值元素的⼦
    数列排序。
    递归的最底部情形,是数列的⼤⼩是零或⼀,也就是永远都已经被排序好
    了。虽然⼀直递归下去,但是这个算法总会结束,因为在每次的迭代
    (iteration)中,它⾄少会把⼀个元素摆到它最后的位置去。

时间复杂度

最优时间复杂度:O(nlogn)
最坏时间复杂度:O(n )
稳定性:不稳定

def quick_sort(li, start, end):
    """快速排序"""
    if start >= end: # 如果开始值大于等于结束值停止
        return
    life = start
    right = end
    mid = li[start]  # 选择一个元素左比较值
    while life < right:
        while life < right and li[right] >= mid:  # 如果左边光标索引值小于右边光标的位置 并且右边的元素大于等于选择的固定元素
            right -= 1  # 右边的光标向左移动一位
        li[life] = li[right]  # 把右边的元素赋值到左边光标的位置
        while life < right and li[life] < mid:  # 如果右边光标索引值小于右边的位置 并且左边的元素大于等于选择的固定元素
            life += 1  # 左边的光标向右移动一位
        li[right] = li[life]  # 把左边的元素赋值到右边的光标的位置
    li[life] = mid  # 把固定的元素赋值给左边光标的位置
    quick_sort(li, start, life - 1)  # 把左边索引位置0到光标索引位置值减一的范围内的元素排序
    quick_sort(li, life + 1, end)  # 把右边光标索引位置的值+1到列表最后得范围内的元素排序


li = [17, 26, 93, 54, 77, 31, 44, 55, 20]
quick_sort(li, 0, len(li) - 1)
print(li)

归并排序

归并排序是采⽤分治法的⼀个⾮常典型的应⽤。归并排序的思想就是先递归
分解数组,再合并数组。
将数组分解最⼩之后,然后合并两个有序数组,基本思路是⽐较两个数组的
最前⾯的数,谁⼩就先取谁,取了后相应的指针就往后移⼀位。然后再⽐
较,直⾄⼀个数组为空,最后把另⼀个数组的剩余部分复制过来即可。

时间复杂度

最优时间复杂度:O(nlogn)
最坏时间复杂度:O(nlogn)
稳定性:稳定

def merger_sort(li):
    """归并排序"""
    n = len(li)
    if 1 == n:  # 如果列表的元素剩余一个 停止拆分
        return li
    mid = n // 2  # 把列表以长度/2拆分成两个部分
    left_sort = merger_sort(li[:mid])   # 把分开的别表左侧赋值给left_sort
    right_sort = merger_sort(li[mid:])  # 把分开的别表右侧赋值给right_sort

    left, right = 0, 0  # 定义变量起始位置
    alist = []  # 创建列表
    left_n = len(left_sort)  # 定义左边列表的长度
    right_n = len(right_sort)  # 定义右边列表的长度
    while left < left_n and right < right_n:   # 左右两边的长度大于0进入循环
        if left_sort[left] <= right_sort[right]:  # 判断左边列表的元素小于等于右边元素
            alist.append(left_sort[left])   # 把左边的元素加入到新的列表
            left += 1  # 左边位置加1
        else:
            alist.append(right_sort[right])  # 否则把右边的元素加入到新的列表
            right += 1  # 右边位置+1
    alist += left_sort[left:]  # 把对比完剩余的元素添加到列表
    alist += right_sort[right:]

    return alist


li = [17, 26, 93, 54, 77, 31, 44, 55, 20]


print(merger_sort(li))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值