1. 程式人生 > >氣泡排序法&定向氣泡排序法的Python實現

氣泡排序法&定向氣泡排序法的Python實現

氣泡排序法

氣泡排序法:每輪對相鄰的兩者進行比較,若順序不對,則進行位置互換,每輪都將使每輪的
最後一位是該輪的大數。
比如在數列:[71, 1, 14, 78, 75, 38, 10, 49, 40, 95]
第一輪交換:71>1 ==> [1, 71, 14, 78, 75, 38, 10, 49, 40, 95];
                      71>14 ==> [1, 14, 71, 78, 75, 38, 10, 49, 40, 95];
                      71<78 ==> pass
                      78>75 ==> [1, 14, 71, 75, 78, 38, 10, 49, 40, 95];
                      ....直到[1, 14, 71, 75, 38, 10, 49, 40, 78, 95],進行下一輪的交換
如此每一輪的比較結果:
原資料: [11, 71, 15, 65, 24, 10, 41, 23, 53, 48]


第1輪:[11, 15, 65, 24, 10, 41, 23, 53, 48, 71]
第2輪:[11, 15, 24, 10, 41, 23, 53, 48, 65, 71]
第3輪:[11, 15, 10, 24, 23, 41, 48, 53, 65, 71]
第4輪:[11, 10, 15, 23, 24, 41, 48, 53, 65, 71]
第5輪:[10, 11, 15, 23, 24, 41, 48, 53, 65, 71]
第6輪:[10, 11, 15, 23, 24, 41, 48, 53, 65, 71]
第7輪:[10, 11, 15, 23, 24, 41, 48, 53, 65, 71]
第8輪:[10, 11, 15, 23, 24, 41, 48, 53, 65, 71]
第9輪:[10, 11, 15, 23, 24, 41, 48, 53, 65, 71]
第10輪:[10, 11, 15, 23, 24, 41, 48, 53, 65, 71]

我們可以看到每一輪參與比較的數的最後一位都將是該輪最大的數。
需要注意的是:每一輪的最大數退出下一輪的比較比如第一輪比較索引值(0~9)這段位置的數,
到了第二輪就只比較索引值(0~8)這一段位置的數...。

程式碼實現

import time
import random
from copy import deepcopy 

def buble_order(deal):   
    op = deepcopy(deal)
    for i in range(len(op)):
        for j in range(len(op)-i-1):
            if op[j] > op[j+1]:
                temp = op[j]
                op[j] = op[j+1]
                op[j+1] = temp
            else:
                pass
        #print(op)
    return op

if __name__ == '__main__':    
    base = [random.randint(1,100) for _ in range(10)]
#    base = [71, 1, 14, 78, 75, 38, 10, 49, 40, 95]
    print('原資料:',base)
    
    start1 = time.time()
    op1 = buble_order(base)
    end1 = time.time()
    print('氣泡排序耗時:%s' % (end1-start1))
    print(op1)

氣泡排序法在時間效能上還是有些弱的,於是有人提出了定向排序法(雞尾酒排序法)

雞尾酒排序法

雞尾酒排序法與氣泡排序法有一點不同的是:氣泡排序法每一輪從左向右,最終推出該輪的最大數在每一輪的右端浮現;而雞尾
酒排序法每一輪找出該處當前輪(參與排序的數)裡的最大數與最小數,置於左右兩端。從左右兩端縮減每一輪的排序範圍。
換句話說氣泡排序法每次冒一個泡(每一輪最大的泡泡),雞尾酒排序法每次冒兩個泡(每一輪最大的泡泡和最小的泡泡),
氣泡排序法每一輪都能使靠右端的資料有序,而雞尾酒排序法每一輪能使靠右端的資料和靠左端的資料有序,基於此,在速度
上雞尾酒排序是比氣泡排序速度要快一點的。

程式碼實現

def buble_orient_order(deal):
    op = deepcopy(deal)
    
    num_min = num_max = op[0]
    index_min = index_max = 0
    left = 0#左端
    right = len(op)-1#右端
    
    while left < right:#如果設定為left != right的條件,那麼就會導致奇數個數的數排序正確,偶數個數的數異常
        for i in range(left,right+1):
            if num_min > op[i]:
                num_min = op[i]
                index_min = i                 
            if num_max < op[i]:
                num_max = op[i]
                index_max = i
         
        #交換位置
        op[index_min],op[left] = op[left],op[index_min]
        op[index_max],op[right] = op[right],op[index_max]
        left += 1
        right -= 1

        num_min = num_max = op[left]
        index_min = index_max = left
        
    return op

兩種排序的比較:

if __name__ == '__main__':    
    base = [random.randint(1,100) for _ in range(10)]
#    base = [71, 1, 14, 78, 75, 38, 10, 49, 40, 95]
    print('原資料:',base)
    
    start1 = time.time()
    op1 = buble_order(base)
    end1 = time.time()
    print('氣泡排序耗時:%s' % (end1-start1))
    print(op1)
    
    print('-'*25)
#    print('原資料:',base)
    
    start2 = time.time()
    op = buble_orient_order(base)
    end2 = time.time()
    print('雞尾酒排序耗時:%s' % (end2-start2))
#    print(op)

這是我們的主函式,通過改變random.ranint()函式中的引數,調整隨機取數的範圍;通過調整range()函式中的引數,調整
需要排序的數的個數。
現在我們先直接在上面的引數下執行,執行結果:

可以發現兩者的執行時間沒什麼差別,現在我們將前面提到的引數修改,我們將取數範圍修改成(1,1000),取的個數修改
為(1000),我們遮蔽掉資料列印語句(不然資料太多,干擾觀察):

我想你已經看出區別了,這個區別目前很小,可是但你把數的個數繼續放大,你就會發現時間的明顯差距。當然了,這兩種
方法還是不夠快的。