数据结构学习——08—排序算法(插入排序、希尔排序、快速排序)

一、插入排序(insertion sort)
将数组中的数据分为两个区间,已排序区间和未排序区间。初始已排序区间只有一个元素,就是数组的第一个元素。插入算法的核心思想是取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束。(抓扑克牌形式)
在这里插入图片描述
插入排序包含元素的比较和元素的移动。将一个数据 a 插入到已排序区间时,需要拿 a 与已排序区间的元素依次比较大小,找到合适的插入位置。找到插入点之后,还需要将插入点之后的元素顺序往后移动一位,这样才能腾出位置给元素 a 插入。

# 插入排序
'''
将数组中的数据分为两个区间,已排序区间和未排序区间。初始已排序区间只有一个元素,就是数组的第一个元素。
插入算法的核心思想是取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。
重复这个过程,直到未排序区间中元素为空,算法结束。
(抓扑克牌形式)
'''
'''
li = [3,            4,57,32,13,46,21,55,77,0,6]
      0             1  2  3...
  
                
li = [0,  3,  4,            57,32,13,46,21,55,77,6]
     j-2 j-1  j             i  i+1...

'''
li = [3,4,57,32,13,46,21,55,77,0,6]

def insert_sort():
    for i in range(1, len(li)):                # 从第2个开始循环,因为列表第一个元素默认排序完成
        for j in range(i, 0, -1):              # 未排序列的第一个元素i,排序之后的最后一个元素j,需要倒叙循环
            if li[j] < li[j-1]:                # 需要和排序完成的j数列进行比较大小
                li[j], li[j-1] = li[j-1], li[j]        # 交换数值
    print(li)

insert_sort()

插入排序算法是稳定算法,它的时间复杂度是O(n).

二、希尔排序(shell sort)

希尔排序,也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。

运行原理:先选取数组长度n除以2的步长gap(gap = len(li) // 2),拆分成不同的几组数列,分别各自组进行排序,然后缩小步长(gap = gap // 2),继续分为几组,每组各自排序,直到gap缩小为1,此时分成一组数列进行排序,完成就是要得到的有序数组。


# 希尔排序
'''
      [3,     4,    57,     32,     13,    46,    21,    55,      77]
       3                            13                            77
              4                            46
                    57                            21
                           32                            55
上面是gap=4时候,将数组拆分成不同的几组数列,单独排序 ,排序完成之后是
        3                            13                            77
              4                            46
                    21                            57
                           32                            55
        3     4     21     32       13     46     57     55       77
然后gap//2=2,继续拆分为:
        3           21              13            57              77
              4            32              46            55
排序结果为:
        3          13               21            57              77
              4            32              46            55
        3     4    13      32       21     46     57     55       77
gap//2=1,继续排序为:
        3     4    13      21       32     46     55     57       77
完成希尔排序
'''
li = [3,4,57,32,13,46,21,55,77]
def shell_sort():
    gap = len(li) // 2             # python3中9/2=4.5    9//2=4    四舍六入五成双
    while gap > 0:                               # gap不断缩小,等于1的时候,排序完成
        for i in range(gap, len(li)):            # 循环从gap开始,是为了容易写li[i-gap]和li[i]代表元素
            while i >= gap and li[i-gap] > li[i]:     # 
                li[i-gap],li[i] = li[i], li[i-gap]    # 数据交换
                i -= gap                              # 不同的组别,进行不同的排序   所以i的值根据gap来改变
        gap = gap // 2                                # 缩小gap直到为1
        print(li)

shell_sort()

四舍六入五成双”规则如下:

“四舍六入五成双”,也即“4舍6入5凑偶”,这里“四”是指≤4 时舍去,"六"是指≥6时进上。"五"指的是根据5后面的数字来定,当5后有数时,舍5入1;当5后无有效数字时,需要分两种情况来讲:5前为奇数,舍5入1;5前为偶数,舍5不进(0是偶数)。
一、具体计算规则:
(1)被修约的数字小于5时,该数字舍去;
(2)被修约的数字大于5时,则进位;
(3)被修约的数字等于5时,要看5前面的数字,若是奇数则进位,若是偶数则将5舍掉,即修约后末尾数字都成为偶数;若5的后面还有不为“0”的任何数,则此时无论5的前面是奇数还是偶数,均应进位。

希尔排序算法时间复杂度
最优时间复杂度:根据步长序列的不同而不同
最坏时间复杂度:O(n^2)

发布了50 篇原创文章 · 获赞 9 · 访问量 2098

猜你喜欢

转载自blog.csdn.net/weixin_42118531/article/details/103146762