常見排序算法心得-侏儒,快速,冒泡,選擇

幾種算法實例

-- 記錄了幾種比較常用的算法,具體的也參考了很多文章,下面是我自己記錄.侏儒 ,冒泡,選擇,插入,快速排序,歸并排序

首先我們介紹一個測試時間的利器,通常情況我們會使用time包來測試,但是只能測試總共的時間,而這個cProfile能測試具體步驟的時間,可以看得非常清楚瓶頸在哪里.

import cProfile   #測試間的利器
def add(a,b):
    return a+b
def for_func():
    result = 0
    for i in range(1000000):
        result += i 
    return result
def main(a,b):
    print 'this is the result for a + b'
    result = add(a,b)
    print result
    print 'test for function'
    print for_func()
cProfile.run('main(1,2)')
this is the result for a + b
3
test for function
499999500000
         115 function calls in 0.144 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 <ipython-input-56-3130e18dd725>:1(add)
        1    0.114    0.114    0.143    0.143 <ipython-input-57-827e3096c393>:1(for_func)
        1    0.000    0.000    0.144    0.144 <ipython-input-58-19c5a6c13393>:1(main)
        1    0.000    0.000    0.144    0.144 <string>:1(<module>)
        9    0.001    0.000    0.001    0.000 iostream.py:180(schedule)
        8    0.000    0.000    0.000    0.000 iostream.py:284(_is_master_process)
        8    0.000    0.000    0.000    0.000 iostream.py:297(_schedule_flush)
        8    0.000    0.000    0.001    0.000 iostream.py:342(write)
        9    0.000    0.000    0.000    0.000 iostream.py:87(_event_pipe)
        9    0.000    0.000    0.000    0.000 threading.py:570(isSet)
        9    0.000    0.000    0.000    0.000 threading.py:986(isAlive)
        8    0.000    0.000    0.000    0.000 utf_8.py:15(decode)
        8    0.000    0.000    0.000    0.000 {_codecs.utf_8_decode}
        8    0.000    0.000    0.000    0.000 {isinstance}
        8    0.000    0.000    0.000    0.000 {method 'decode' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        8    0.000    0.000    0.000    0.000 {nt.getpid}
        9    0.000    0.000    0.000    0.000 {nt.urandom}
        1    0.029    0.029    0.029    0.029 {range}
# 這個表示正無窮,同理-inf表示負無窮,下面我們會用到
float('inf')
inf

侏儒排序法

從第一個數字開始和前面的進行比較,如果小于前面的數字就交換位置然后將指針減少1然后繼續循環檢測下一個. 最后的結果就是講最小的移到第一位,然后從第一位在開始往后就像在紙上來回畫直線一樣每次將最小的數字放到最前面然后從最前面依次往后檢測,知道在找到滿足條件的再次將數字移到前面.

seq = [5,4,3,2,1]
def gnomesort(seq):
    i = 0 
    while i <len(seq):
        if i == 0 or seq[i-1] <= seq[i]:
            i += 1
        else:
            seq[i-1], seq[i] = seq[i], seq[i-1]
            i -= 1
    return seq
gnomesort(seq)

[1, 2, 3, 4, 5]

插入排序

從第一個開始,用這個數字和之前的每一個數字進行比較直到比他前一個數字小為止,那么這個數字的位置就可以確定了-放到他的前面.當然這個排序是從index = 0 開始的.

seq = [5,4,3,2,1]
# 遞歸版插入排序
def ins_sort_rec(seq,i):
    '''
    遞歸是從最低層開始排序的也就是從索引為0的地方開始排序的
    seq 是一個列表,i是列表的長度減1,也就是最后一個元素索引的位置.返回一個排序好的列表
    '''
    if i == 0:return seq
    ins_sort_rec(seq,i-1)   # 這個遞歸的使用可以理解為替換,將函數替換為這個函數的除去函數體的其他部分.
    j = i 
    while j > 0 and seq[j-1]> seq[j]:
        seq[j-1],seq[j] = seq[j],seq[j-1]
        j -= 1
    return seq
        
ins_sort_rec(seq,len(seq)-1)
[1, 2, 3, 4, 5]
# 插入排序 普通版
def ins_sort_nor(seq,i):
    '''seq 是一個列表,i是列表長度-1,這里用這個數字和他前一個數字進行比較如果小于就互換位置,互換后繼續檢查和前一個的大小比較,直到小于位置.
    '''
    for x in range(0,i):
        while x > 0 and seq[x-1] > seq[x]:
            seq[x-1],seq[x] = seq[x], seq[x-1]
            x -= 1
    return seq
    
ins_sort_nor(seq,len(seq)-1)
[1, 2, 3, 4, 5]

選擇排序

選擇排序:第一次將最大的放到最后,然后將剩下的所有中最大的放到最后,依次放到最后一個.

這個排序是從數列的最后一位開始的.

seq = [5,4,3,2,1]
# 遞歸版選擇排序
def sel_sort_res(seq,i):
    if i == 0: return seq
    max_j = i 
    for x in range(i):
        if seq[x] > seq[max_j]:
            seq[x],seq[max_j] = seq[max_j],seq[x]
    return sel_sort_res(seq,i-1)
sel_sort_res(seq,len(seq)-1)
[1, 2, 3, 4, 5]
def sel_sort_nor(seq):
    for i in range(len(seq)-1,0,-1):
        max_j = i 
        for j in range(i):
            if seq[j] >seq[max_j]:max_j = j
        seq[i],seq[max_j] = seq[max_j],seq[i]
    return seq
sel_sort_nor([2,4,1])
[1, 2, 4]

快速排序

快速排序的邏輯是: 每次選中一個參考值,然后把大于參考值的放到右邊小于參考值的放到左邊,這樣就可以確定參考值的位置,每次確定一個參考值的位置,循環往復就可以逐步確認每個數字的位置了

def QuickSort(myList,start,end):
    #判斷low是否小于high,如果為false,直接返回
    if start < end:
        i,j = start,end
        #設置基準數
        base = myList[i]  

        while i < j:  
            #如果列表后邊的數,比基準數大或相等,則前移一位直到有比基準數小的數出現
            while (i < j) and (myList[j] >= base):  
                j = j - 1  

            #如找到,則把第j個元素賦值給第個元素i,此時表中i,j個元素相等
            myList[i] = myList[j]

            #同樣的方式比較前半區
            while (i < j) and (myList[i] <= base):
                i = i + 1
            myList[j] = myList[i]
        #做完第一輪比較之后,列表被分成了兩個半區,并且i=j,需要將這個數設置回base
        myList[i] = base

        #遞歸前后半區
        QuickSort(myList, start, i - 1)
        QuickSort(myList, j + 1, end)
    return myList


myList = [49,38,65,97,76,13,27,49]
print("Quick Sort: ")
QuickSort(myList,0,len(myList)-1)
print(myList)
Quick Sort: 
[13, 27, 38, 49, 49, 65, 76, 97]
# 快速排序
def quick_sort(seq,start,end):
    if i < j: 
        i,j = start,end
        base = seq[i]
        while i <j:
            while i < j and seq[j] >= base:
                j -= 1
            seq[i] = seq[j]
            while i < j and seq[i] <= base:
                i += 1
            seq[j] = seq[i]
        seq[i] = base
    
    quick_sort(seq,start, i -1)
    quick_sort(seq,j+1,end)
    
    return seq
myList = [49,38,65,97,76,13,27,49]
print("Quick Sort: ")
quick_sort(myList,0,len(myList)-1)
print(myList)
Quick Sort: 
[13, 27, 38, 49, 49, 65, 76, 97]

冒泡排序

def bubble_sort(seq,order=1):
    end = len(seq)-1
    for x in range(end,0,-1):
        for y in range(x):
            if order == 1:
                if seq[y] > seq[y+1]:
                    seq[y],seq[y+1] = seq[y+1],seq[y]
            
    return seq
alist = [4,3,2,1,5,7,4,5,4,3,2,4,5,6,7,78,87,6,54,3,3]
bubble_sort(alist)
[1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 54, 78, 87]

這個算法中,最好的時間復雜度是 n, 最差的時間復雜度是n**2 所以是時間復雜度應該介于這兩者之間

歸并排序法

def mergesort(seq):
    mid = len(seq)//2
    lft, rgt = seq[:mid],seq[mid:]
    if len(lft) > 1 : lft = mergesort(lft)
    if len(rgt) > 1 : rgt = mergesort(rgt)
    res = []
    while lft and rgt:
        if lft[-1] >= rgt[-1]:
            res.append(lft.pop())
        else:
            res.append(rgt.pop())
    res.reverse()
    return (lft or rgt) + res    

如何從某一個數字列表中找出彼此最接近但是不相等的兩個數:

思路: 找出兩個數字的絕對差最小,兩次遍歷整個列表,兩個數的差值比較如果比上一個小那么就取用這個差值和這兩個數字

alist = [1,2,5,3,5,3.122,12,23.43,79,4,8.1,8.12]
dd = float('inf')
for x in alist:
    for y in alist:
        if x == y : continue
        d = abs(x - y)
        if d < dd:
            xx, yy,dd = x, y,d
xx,yy  # 對于這個算法來說,時間復雜度是平方級的
(8.1, 8.12)

如果使用排序好的列表進行排序速度將會提高

newlist = sorted(alist)  # 如果使用list.sort() 方法那么原本的list的排序就會改變慎用
i = 0
dd = float('inf')
while i < len(newlist)-1:
    if newlist[i] == newlist[i+1]: 
        i +=1
    else:
        d = abs(newlist[i] - newlist[i+1])
        if d < dd:
            x,y,dd = newlist[i],newlist[i+1],d
        i += 1
x,y
(1, 2)

幾種排序的思想以及方法

冒泡算法思想:

每次相鄰元素進行比較,如果發現較小的元素在后面,就交換兩個相鄰的元素,每次循環都將最大是數據排列到結尾處.

選擇排序算法思想:

在冒泡排序上做了優化,減少了交換次數,在首輪選擇最大的數放在第一項,一輪之后第一項是有序的了,第二輪從第二項開始選擇最大的數放在第二項,以此類推,直到整個數組完全有序

插入排序算法思想:

和前倆種排序不同,插入排序在排序過程中是局部有序,隨著插入項的增多,有序部分的項的位置會發生改變,而冒泡排序和選擇排序每輪確定的項數的位置是永遠不變的。在首輪,選擇第二項作為插入項,然后取出這一項放在一個變量中,和前一項比較而且小,則前一項后移到第二項的位置,然后第二項也就是插入項放在前一項的位置,第二輪選擇第三項作為插入項然后取出和前一項也就是第二項比較如果小,第二項后移到插入項,然后插入相在和第一項比較如果小,則第一項后移到第二項,插入項放在第一項,以此類推。

總結:

冒泡算法,每次比較如果發現較大的元素在后面,就交換兩個相鄰的元素。而選擇排序算法的改進在于:先并不急于調換位置,先從Aarray[0]開始逐個檢查,看哪個數最大就記下該數所在的位置j,等一躺掃描完畢,再把Arraymax和A[0]對調,這時Array[0]到Array[6]中最大的數據就換到了最前面的位置。所以,選擇排序每掃描一遍數組,只需要一次真正的交換,而冒泡可能需要很多次,比較的次數是一樣的。插入排序算法比冒泡快一倍,比選擇排序略快一點

seq = [7,5,3,56,7,8,3,12,2]
# 冒泡排序
def bubble_sort(seq):
    # 索引的位置
    i = len(seq)-1
    for x in range(i,0,-1):
        for y in range(x):
            if seq[y]<seq[y+1] :
                seq[y+1] , seq[y] = seq[y] ,seq[y+1]
    return seq    
bubble_sort(seq)
[56, 12, 8, 7, 7, 5, 3, 3, 2]
seq
[7, 7, 7, 7, 7, 7, 7, 12, 12]
# 侏儒算法
def gon_sort(seq,end):
    i = 0
    while i < end:
        if  i == 0 or seq[i-1] <= seq[i]:
            i += 1
        else:
            seq[i-1],seq[i] = seq[i],seq[i-1]
            i -= 1
    return seq
seq = [7,5,3,56,7,8,3,12,2,5,3,21,6]
end = len(seq)
gon_sort(seq,end)
[2, 3, 3, 3, 5, 5, 6, 7, 7, 8, 12, 21, 56]
def quick_sort(seq,start,end):
    if start < end:
        i,j = start,end
        base = seq[i]
        while i < j:
            while i < j and seq[j] >= base:
                j -= 1
            seq[i] = seq[j]
            while i < j and seq[i] <= base:
                i += 1
            seq[j] = seq[i] 
        seq[i] = base
        
        quick_sort(seq,start,i-1)
        
        quick_sort(seq,j+1,end)
    return seq
seq = [7,5,3,56,7,8,3,12,2,5,3,21,6]
start = 0
end = len(seq)-1
quick_sort(seq,start,end)
[2, 3, 3, 3, 5, 5, 6, 7, 7, 8, 12, 21, 56]
def select_sort(seq,end):
    for x in range(end,0,-1):
        max_j = end 
        for y in range(x):
            if seq[y]>seq[max_j]: max_j = y
        
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,676評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,730評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,873評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,266評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,482評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,036評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,846評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,025評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,279評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,751評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,016評論 2 375

推薦閱讀更多精彩內容