经典排序算法系列之插入排序和希尔排序----小白理解(python)
Posted Echo Result
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了经典排序算法系列之插入排序和希尔排序----小白理解(python)相关的知识,希望对你有一定的参考价值。
继续跟进上篇文章,今天研究和理解下插入排序和希尔排序
一、插入排序
4次排序结果图示:
原理:
从第一个元素开始,该元素可以认为已经被排序;
取出下一个元素,在已经排序的元素序列中从后向前扫描;
如果该元素(已排序)大于新元素,将该元素移到下一位置;
重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
将新元素插入到该位置后;
重复步骤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
for j in range(i-1, -1, -1):
if tmp < int(n[j]):
n[j+1] = n[j]
insertIndex = j
else:
break
n[insertIndex] = tmp
print(n)
总结:
插入排序最主要的就是记录当前要插入的数和下标。下标在遍历有序区的时候要变成当前遍历到的有序区的下标,这样是为了记录要插入的下标,在遍历结束后就插入。如果满足要插入的数大于遍历有序区的数,就退出循环,因为找到插入点了。为什么else中就一个break,而不需要insertIndex = j呢?因为不满足if tmp < int(n[j])就代表此时下标为j那个数就是不满足的值,需要将要插入的数插入到j+1中,而此时insertIndex就是此时的j+1啦,所以最后就将 tmp赋值给n[insertIndex]。这位大佬直接在if中调换,导致后面的有序区的插入进行了一次冒泡排序,但结果没错的。大佬提出的改进意见非常厉害,在有序区进行二分查找(二分插入排序)插入,在大量数据的时候,会非常之快。插入排序在整体数据基本有序的状态下是很快的。
二、希尔排序
图示:
原理:
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:
选择一个增量序列t1,t2,…,ti,tj,…,tk,其中ti>tj,tk=1;
按增量序列个数k,对序列进行k 趟排序;
每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
特性:
平均时间复杂度O(n^1.3),空间复杂度O(1),内排序,不稳定
自我解析:
之前说插入排序在基本有序的状态下速度会很快。希尔排序其实就是结合插入排序,利用一个增量(依次递减)等差进行直接插入排序。这个看图很容易理解,不同颜色的数字为同一组进行。增量一开始一般是数组长度的2分之1,不能整除就向下取整。但是遇到不是偶数的时候,那个多出来的怎么对比,
代码:
n = input()
n = [i for i in n.split()]
len = len(n)
gap = len // 2
while gap >= 1:
for i in range(gap, len):
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
print(n)
总结:
希尔排序难点就在于控制遍历边界,特别是len不是偶数的时候。
以上是关于经典排序算法系列之插入排序和希尔排序----小白理解(python)的主要内容,如果未能解决你的问题,请参考以下文章