數據結構複習總結之希爾排序(三)

先來看一下希爾排序:

原理概述

希爾排序其實是插入排序的改進版本,性能會有所提升,該算法設置一個gap步長(後續會變化),選取原序列的隔步長的元素組成一個子表,對該子表使用插入排序,其實很明顯的就是每設置一個步長該原序列就會被分成gap個子表,對所有子表都分別進行插入排序,也就是在各自的表順序內進行插入排序,但是操作的元素仍是原表中對應的索引(而不是新的子表中的索引,所以子表中每兩個元素之間的間隔爲gap)。接下來再讓gap減半,這樣子表的數目減少,每個子表中的元素變多,然後對這些新的子表仍然進行插入排序,接下來再讓gap減半,再對生成的新的子表插入排序,,,以此類推,知道最後gap=1也就是會有一個原序列作爲子表(其實只是順序不一樣了,長度還是原序列的長度,因爲步長爲1嘛)

代碼實現

我發現我的智商真的有問題,,,,,想了好久,,,,我,,,

# -*- coding: utf-8 -*-
"""
Created on Sat May 26 13:45:51 2018

@author: Administrator
"""

#**********************************希爾排序**********************************
def Shell_sort(L):
    n=len(L)
    gap=n//2
    while gap>=1:
        for i in range(gap):  #0,1,2,3
            member=int((n-1-i)/gap)+1  #每一組有多少元素 #3,
            for j in range(1,member):
                for k in range(j,0,-1):
                    if L[i+k*gap]<L[i+k*gap-gap]:
                        L[i+k*gap],L[i+k*gap-gap]=L[i+k*gap-gap],L[i+k*gap]
        print(L)
        gap=int(gap/2)

    print(L)        

if __name__=="__main__":
    Shell_sort([2,6,1,3,0,4,8,5])
結果展示
[0, 4, 1, 3, 2, 6, 8, 5]
[0, 3, 1, 4, 2, 5, 8, 6]
[0, 1, 2, 3, 4, 5, 6, 8]
[0, 1, 2, 3, 4, 5, 6, 8]

這裏我把初始步長設爲4,然後每次減半,把每次結果都打印了(4,2,1對應三個排序結果)最後一個是最終排好的我又打印了一次。

雖然寫出來了,可是並不是秒做,,不開心。

嗯,剛纔看了一下老師的解決思路,發現又被秒了好嘛,哼
先說一下具體的思路:

解題思路

首先就是把原始的序列分成gap份 也就相當於有gap個子序列,我們需要對當前gap下劃分的這gap個子序列進行初步排序,也就是此次gap結束後每一個子序列都必須排好序,然後對於下一次gap劃分仍然採取上述步驟進行插入排序
先把數據分爲子序列的第一個元素和子序列需要比較(插入)的元素,然後對於後邊一部分元素,我們不是把第一個子序列都比較好之後再開始第二個子序列的排序,而是把子序列待排序部分的第一個進行插入排序,因爲他們都是gap,gap+1,gap+2,,,n-1 這些值,他們前面的元素都是各自索引-gap即可(說的好囉嗦,直接看代碼比較好)

嗯,看懂老師的思路之後自己又寫了一個,思路是一樣的,如下:
嗯,發現我還是不太喜歡用while,略略略~

#*************************希爾排序(by_teacher)***************************
def Shell_sort2(L):
    n=len(L)
    gap=n//2 #設置gap步長
    print("希爾排序之前:",L)
    while gap>=1:

        for i in range(gap,n):#插入排序的遍歷次數(對於此gap下)
            for j in range(i,0,-gap):
                if L[j]<L[j-gap]:
                    L[j],L[j-gap]=L[j-gap],L[j]
        gap//=2
    print("希爾排序之後:",L)
結果展示
希爾排序之前: [2, 6, 1, 3, 0, 4, 8, 5]
希爾排序之後: [0, 1, 2, 3, 4, 5, 6, 8]
時間複雜度

關於希爾排序,其實本質上就是插入排序的升級版,所以當你取gap=1時它就是插入排序,所以最壞的時間複雜度就是O(n^2)
最好的時間複雜度取決於gap的選擇

穩定性

雖然插入排序是穩定的,但是希爾排序卻不是,因爲希爾排序實現對子序列進行排序,也就是對於每一個gap,都是把各個子序列排好序,比如
12,94,77,77,89,1
取gap=2,那麼兩個子序列:
12,77(前面的77),89
94,77(後邊的77),1
對於第二個子序列,插入排序之後,77(後面的)就會跑到第一個位置
而第一個子序列的77(前面的)仍然在原來的位置
這樣一來當gap=1插入排序時原序列後面的77就會比原序列前面的77位於更前的位置,所以該算法不穩定

排序算法比較

最後三個(堆排序,歸併排序,快速排序)接下來就會有啦
排序算法比較

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章