吃透排序算法之遍历排序

吃透排序算法之遍历排序

排序算法不仅仅是无序到有序, 其中涉及了数组的遍历处理, 划分的模板运用, 甚至其中还设计到了数组到树的堆化处理. 可以说吃透了排序算法, 可以成为一个合格的算法初学者了.

本系列文章带领读者吃透排序算法, 掌握数组的处理方式, partition模板, 数组的二叉树形式并进行堆化处理.

吃透排序算法之遍历排序为本系列的遍历排序介绍, 主要介绍几种入门的排序, 本文主要涉及:

  • 冒泡排序
  • 选择排序
  • 插入排序
  • 希尔排序

冒泡排序

冒泡排序是第一个要学习的排序算法, 过程像冒泡一样. 假设数组长度为n, 冒泡排序将进行n趟, 每一趟元素交换过程如同气泡从小到大, 最终得到一个排序好的数组.

冒泡排序交换相邻元素, 内层数组每次会后移一位, 直到排序好的位置, 外层数组控制n趟.

nums = [1, 3, 2, 5, 4, 6]


i = 0
while i < len(nums):
    j = 0
    while j < (len(nums)-1)-i:
        if not (nums[j] <= nums[j+1]):
            nums[j], nums[j+1] = nums[j+1], nums[j]
        j += 1
    i += 1

print(nums) # [1, 2, 3, 4, 5, 6]

进一步的过程中冒泡排序可能就排序完成, 可以通过flag优化算法.

nums = [1, 3, 2, 5, 4, 6]


i = 0
while i < len(nums):
    j, swap = 0, False # 定义flag
    while j < (len(nums)-1)-i:
        if not (nums[j] <= nums[j+1]):
            swap = True # 赋值flag
            nums[j], nums[j+1] = nums[j+1], nums[j]
        j += 1
    if not swap: # 通过flag提前结束
        break
    i += 1

print(nums) # [1, 2, 3, 4, 5, 6]

选择排序

选择排序的处理方式和冒泡排序有很大不同, 顾名思义选择一个最值来放到有序区. 每轮只进行一次交换, 比冒泡少多了. 数组被划分有有序区和无序区, 每次选择最小元素和下一个无序位置交换. 最小值可以选择索引, 索引可以初始化成和当前无序位置相同的数值, 并不需要设置一个最小的值-inf.

nums = [1, 3, 2, 5, 4, 6]


i = 0
while i < len(nums):
    j, minidx = i, i
    while j < len(nums):
        if nums[j] < nums[minidx]:
            minidx = j
        j += 1
    nums[i], nums[minidx] = nums[minidx], nums[i]
    i += 1

print(nums) # [1, 2, 3, 4, 5, 6]

插入排序

插入排序类似于冒泡排序, 主要是因为相邻元素, 不同点就是冒泡是向数值尾部冒泡, 插入则是想数组头部冒泡. 这个说法可能不准确, 因为冒泡过程可能随时停止, 更像是插入, 所以名为插入排序.

 nums = [1, 3, 2, 5, 4, 6]

# 插入排序相临
i = 0
while i < len(nums):
    j = i
    while j > 0:
        if not (nums[j-1] <= nums[j]):
            nums[j], nums[j-1] = nums[j-1], nums[j]
        j -= 1
    i += 1

print(nums) # [1, 2, 3, 4, 5, 6]

希尔排序

试想一种情况, [2,3,4,5,6,1]如果使用插入排序, 1要跨过整个数组, 显然有点拖累. 是否可以加速这一过程呢? 考虑是否可以去掉相邻的考虑, 改成跨gap的相隔呢? 这样就可以避免这种情况出现. 数组将在gap缩小的过程趋近整体有序, 最终gap为1时退化成插入排序.

nums = [2, 3, 4, 5, 6, 1]


def insert(gap): # 插入排序相隔gap
    i = 0
    while i < len(nums):
        j = i
        while j > 0:
            if not (nums[j-gap] <= nums[j]):
                nums[j], nums[j-gap] = nums[j-gap], nums[j]
            j -= gap
        i += gap


gap = int(len(nums)/2) # 通常gap选取N/2
while gap > 0:
    insert(gap)
    gap -= 1

print(nums) # [1, 2, 3, 4, 5, 6]


小结

本文主要对遍历排序做介绍和使用python实现了基本过程. 学习了冒泡排序的实现和优化, 了解了选择排序的交换原理和实现, 学习了插入排序的实现和其极端情况的优化希尔排序.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值