经典排序算法系列之插入排序和希尔排序----小白理解(python)

Posted Echo Result

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了经典排序算法系列之插入排序和希尔排序----小白理解(python)相关的知识,希望对你有一定的参考价值。

继续跟进上篇文章,今天研究和理解下插入排序和希尔排序


一、插入排序

    4次排序结果图示:


 原理:

  1. 从第一个元素开始,该元素可以认为已经被排序;

  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;

  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置;

  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;

  5. 将新元素插入到该位置后;

  6. 重复步骤2~5。


特性:

     平均时间复杂度O(n^2),空间复杂度O(1),内排序,稳定


自我解析:

    插入排序核心思想就是从前往后,以第一个为起点作为有序区,后面依次遍历每个数,遍历的这个数A跟之前的有序区从后往前依次比较,如果A大于遍历的有序区的某个数,就将A插入到有序区某个数的后面,如果A小于这个有序区的某个数,就将某个数往后移一位。


代码:

n = input()n = [i for i in n.split()]len = len(n)#从第二个开始比较,因为第一个肯定是有序区(两个数才能确定正序和逆序啊)for i in range(1,len): #定义一个临时变量记录此时要插入的数字 tmp = int(n[i]) #定义一个临时变量记录要插入数字的起始的位置 insertIndex = i #遍历有序区,倒序和正序遍历都行,这里为了迎合动图,一样从后面遍历有序区 #i-1 为有序区的末尾下标,-1是执行到0(因为python range的第二个参数是开区间,只执行到它的前一位),-1是自减 for j in range(i-1, -1, -1): # 当tmp小于有序区的数时,就将n后移一位,并记录此时的位置,否则就找到要插入的,退出循环 if tmp < int(n[j]): n[j+1] = n[j] insertIndex = j else: break #将此时要插入的数插入insertIndex的位置,如果insertIndex未改变,则为原来的i    n[insertIndex] = tmpprint(n)


总结:

    插入排序最主要的就是记录当前要插入的数和下标。下标在遍历有序区的时候要变成当前遍历到的有序区的下标,这样是为了记录要插入的下标,在遍历结束后就插入。如果满足要插入的数大于遍历有序区的数,就退出循环,因为找到插入点了。为什么else中就一个break,而不需要insertIndex = j呢?因为不满足if tmp < int(n[j])就代表此时下标为j那个数就是不满足的值,需要将要插入的数插入到j+1中,而此时insertIndex就是此时的j+1啦,所以最后就将 tmp赋值给n[insertIndex]。这位大佬直接在if中调换,导致后面的有序区的插入进行了一次冒泡排序,但结果没错的。大佬提出的改进意见非常厉害,在有序区进行二分查找(二分插入排序)插入,在大量数据的时候,会非常之快。插入排序在整体数据基本有序的状态下是很快的。


二、希尔排序

    图示:



 原理:

    先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:

  1. 选择一个增量序列t1,t2,…,ti,tj,,tk,其中ti>tj,tk=1;

  2. 按增量序列个数k,对序列进行k 趟排序;

  3. 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

特性:

     平均时间复杂度O(n^1.3),空间复杂度O(1),内排序,不稳定


自我解析:

    之前说插入排序在基本有序的状态下速度会很快。希尔排序其实就是结合插入排序,利用一个增量(依次递减)等差进行直接插入排序。这个看图很容易理解,不同颜色的数字为同一组进行。增量一开始一般是数组长度的2分之1,不能整除就向下取整。但是遇到不是偶数的时候,那个多出来的怎么对比,


代码:

n = input()n = [i for i in n.split()]len = len(n)# 让步长从大变小,最后一步必须是1,获取gap的偏移值gap = len // 2while gap >= 1: #从gap开始循环后面 for i in range(gap, len): #限制往前遍历小于0 while i - gap >= 0: # 这里使用插入排序,如果后面的小于前面的换位,否则就退出 if int(n[i]) < int(n[i - gap]): n[i], n[i - gap] = n[i - gap], n[i] # 更新迁移元素的下标值为最新值 i -= gap else: # 退出循环 break # 每执行完毕一次分组内的插入排序,对gap进行/2细分    gap //= 2print(n)


总结:

   希尔排序难点就在于控制遍历边界,特别是len不是偶数的时候。


以上是关于经典排序算法系列之插入排序和希尔排序----小白理解(python)的主要内容,如果未能解决你的问题,请参考以下文章

十大经典排序之:插入排序 |希尔排序

经典排序算法之希尔排序

图解算法系列之希尔排序

#yyds干货盘点#十大经典排序之:插入排序 |希尔排序

算法讲解Scartch经典算法4之--希尔排序算法

经典排序之希尔排序