python算法与数据结构-希尔排序算法

希尔排序(shell sort)是插入排序的一种,也称缩小增量排序,与普通的插入算法的区别就是gap步长。

希尔排序内层循环逻辑如下所示:

上面的可以分为4组,一个一个的按照插入算法来做,第一组有54 77 20三个元素,第二组是26 31两个元素,第三组是93和44两个元素,第四组是17和55两个元素。上面的可以分为4组,一个一个的按照插入算法来做,第一组有54 77 20三个元素,第二组是26 31两个元素,第三组是93和44两个元素,第四组是17和55两个元素。

上面的按照插入算法交换后较小的数在前面,较大的数在后面。

当gap=1的时候再次执行插入算法,如下所示:

希尔排序外层循环如下所示:

代码如下所示:

# coding:utf-8
def shell_sort(alist):
      """希尔排序"""
      n=len(alist)
      gap = n // 2 #相除,因为涉及到/符号,所以又加了一个斜杠
      #print(gap) #4
      #gap变化到0之前,插入算法执行的次数
      #while gap>0:
      while gap >= 1:
          #print('gap值是',gap) #gap值是 4   gap值是 2    gap值是 1
          #下面的for循环是一个gap的情况,gap需求不断缩短,所以在外面又套了一层while的gap循环,上面的gap>0也可以写成gap>=1
          #插入算法,与普通的插入算法的区别就是gap步长
          #外层循环
          for j in range(gap,n):
              #j=[gap,gap+1,gap+2,gap+3,...,n-1]
              #print('外层循环值是',j)
              i = j
              #print('第一次',j,gap,n) #4 4 9
              # 先写内层循环
              while i>0:
                  if alist[i] < alist[i-gap]:
                      #print(i,gap,i-gap) #6 4 2  2 4 -2   8 4 4
                      # print('666')
                      # print(j,i, gap, i - gap) #6 6 4 2   6 2 4 -2   8 8 4 4    8 4 4 0
                      alist[i],alist[i-gap] = alist[i-gap],alist[i]
                      i-=gap
                  else:
                      break
              #break;
          #break;
          #缩短gap步长
          gap //=2
          #print('gap除以2后的值是', gap) #gap除以2后的值是 2 gap除以2后的值是 1 gap除以2后的值是 0


if __name__ == "__main__":
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    shell_sort(li)
    print(li)
"""
[54, 26, 93, 17, 77, 31, 44, 55, 20]
[17, 20, 26, 31, 44, 54, 55, 77, 93]

"""

另外一种实现方式如下所示:

# 创建一个希尔排序的函数
def shell_sort(alist):
    # 需要排序数组的个数
    N = len(alist)
    # 最初选取的步长
    gap = N // 2

    # 根据每次不同的步长,对分组内的数据进行排序
    # 如果步长没有减为1就继续执行
    #while gap > 0:
    while gap >= 1:
        # 对每个分组进行插入排序,
        # 因为插入排序从第二个元素开始,而这里第二个元素的下标就是gap
        # 所以j的起始点是gap
        for j in range(gap, N): # 4 2 1这种,j的开始值是4,后来越来越小  2 1
            # 控制每个分组内相邻的两个元素,逻辑上相邻的两个元素间距为gap,
            # i的前一个元素比它少一个gap距离,所以for循环中j的步长为 -gap
            for i in range(j, 0, -gap):
                # 判断和逻辑上的分组相邻的两个数据大小
                if alist[i] < alist[i - gap] and i - gap >= 0:
                    # 交换
                    temp = alist[i]
                    alist[i] = alist[i - gap]
                    alist[i - gap] = temp
        # 改变步长
        gap = gap // 2


numlist = [5, 7, 8, 3, 1, 2, 4, 6, 9]
print("排序前:%s" % numlist)
shell_sort(numlist)
print("排序后:%s" % numlist)
"""
排序前:[5, 7, 8, 3, 1, 2, 4, 6, 9]
排序后:[1, 2, 3, 4, 5, 6, 7, 8, 9]
"""

猜你喜欢

转载自blog.csdn.net/gb4215287/article/details/107303238