<学习笔记>排序算法4-5:希尔排序+快速排序(2020.7.29)

4. 希尔排序

  • 希尔排序
  • (shell sort)是插入排序的一种,也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本,该方法的基本思想是:先将整个待排序列分割成若干个子序列(由相隔某个"增量(gap)"的元素组成)分别进行直接插入排序,然后一次所见增量在进行排序,待整个序列中的元素基本有序(增量足够小)时,在对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接排序有较大提高。
  • gap:是增量值,也是拆分出来的组数。初始化为gap = length / 2,以后在以上一次的增量除2进行不断缩小更新。
  • 插入排序其实时增量为1的希尔排序
  • 在缩小增量的同时进行插入排序,从而使最后的数列变为有序的。

在这里插入图片描述
原始数组 一下数据元素颜色相同的为一组
在这里插入图片描述
初始增量 gap = length/2 = 5,意味着整个数组被分为5组,[8,3] [9,5] [1,4] [7,6] [2,0]
在这里插入图片描述
对这5组分别进行直接插入排序,结果如下,可以看到,像3,5,6这些小元素都被调到前面了,然后缩小增量,gap = 5/2 = 2,数组被分为了2组[3,1,0,9,7] [5,6,8,4,2]
在这里插入图片描述
对以上2组再分别进行直接插入排序,结果如下,可以看到,此时整个数组的有序成都更进一步了。再次缩小增量gap = 2/2 = 1,此时整个数组被分为了1组[0,2,1,4,3,5,7,6,9,8],如下图所示:
在这里插入图片描述
经过上面的宏观调控,整个数组的有序化成都成果喜人。
此是,仅仅需要对以上数列进行简单微调,无需大量移动操作即可完成整个数组的排序。
在这里插入图片描述
思路: 希尔排序,通过逐步缩小增量,从而可以减小插入的次数。因此代码部分可以根据插入排序的代码进行修改,主要是对需要gap部分进行修改,把原来插入排序的1换成ga怕,再加入一个gap更新就好了。

# 希尔排序

def shellSort(alist):
    gap = len(alist) // 2
    while gap >= 1:
        for i in range(gap, len(alist)):
            while i > 0:
                if alist[i] < alist[i - gap]:
                    alist[i], alist[i - gap] = alist[i - gap], alist[i]
                    i -= gap
                else:
                    break
        gap //= 2
    return alist

alist = [3, 8, 5, 7, 6]
print(shellSort(alist))

5. 快速排序

  • 将列表中第一个元素设定为基准数字,赋值给mid变量,然后将整个列表中比基准小的数值放在基准的左侧,比基准到的数字放在基准右侧。然后将基准数字左右两侧的序列在根据此方法进行排放。
  • 定义两个指针,low指向最左侧,high指向最右侧
  • 然后对最右侧指针进行向左移动,移动法则是,如果指针指向的数值比基准小,则将指针指向的数字移动到基准数字原始的位置,否则继续移动指针。
  • 如果最右侧指针指向的数值移动到基准位置时,开始移动最左侧指针,将其向右移动,如果该指针指向的数值大于基准则将该数值移动到最右侧指针指向的位置,然后停止移动。
  • 如果左右侧指针重复则,将基准放入左右指针重复的位置,则基准左侧为比其小的数值,右侧为比其大的数值。
    在这里插入图片描述

算法步骤:
(1)从数列中挑出一个元素,称为 “基准”(pivot);
(2)重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
(3)递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

def quickSort(alist, start, end):
    low = start
    high = end
    # 递归结束的条件
    if low > high:
        return
    # 基准:最左侧的数值
    mid = alist[low]
    # low和high的关系只能是小于,当等于的时候就要填充mid了
    while low < high:
        while low < high:
            if alist[high] > mid:
                high -= 1
            else:
                alist[low] = alist[high]
                break
        while low < high:
            if alist[low] < mid:
                low += 1
            else:
                alist[high] = alist[low]
                break

        # 当low和high重复的时候,将mid填充
        if low == high:
            alist[low] = mid  # or alist[high] = mid
            break
    # 执行左侧序列
    quickSort(alist, start, high - 1)
    # 执行右侧序列
    quickSort(alist, low + 1, end)

    return alist



alist = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8]
print(quickSort(alist,0,9))

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值