插入選擇冒泡快速,四種常見排序與效率測試

一、在常見的四種排序中(插入選擇冒泡快速),很多時候由於對其適用的環境不夠了解,我們可以嘗試將其包裝成一個類,並提供幾個可以直接調用的類方法,便於日後的測試與深入理解。

由於要進行效率測試,所以需要一個裝飾器作包裝類內部方法,但在設計上,若將其封裝與類內部,相比外部會使程序更加緊湊,而方法調用方面,由於排序方法可能很多,故不應該直接賦值於類,因爲這樣的賦值以後可能會導致使得類內部的數據混亂,所以應該爲其提供一些類方法供直接調用,在編寫思想上也將更加靈活。

由於列表的內存與賦值機制,使用deepcopy方法深拷貝測試,以防止被其他方法篡改數據,失去測試意義。

二、四種排序思想上的實現:

冒泡:左右兩兩相比,一遍找出一個極值。

選擇:一遍比一值,隨着運行後期比冒泡少比較很多值,理論效率高於冒泡。

插入:數據只與前面進行對比,目的只是找到自己的合適位置後,將其數據插入

快速:將數據兩兩分之,找出一個基準值作爲界限,隨後再次將其遞歸,重複直到low與high相等。

代碼實現:

# Sort class          
import time
import random
import sys
import copy

#解鎖最大遞歸數,防止快速排序溢出
sys.setrecursionlimit(1000000)  

"""
使用生成器實現可迭代的任意範圍任意數量的數字
並給出get_list()方法可供調用生成列表
"""

class Rand_Iter(object):        
    def __init__(self, start, stop, num):
        self.start = start
        self.stop = stop
        self.num = num
        self.list = []

    def get_iter(self):
        while self.num > 0:
            rand = random.randint(self.start, self.stop)
            yield rand
            self.num -= 1

    def get_list(self):
        self.list = []
        self.iter = self.get_iter()
        if iter is not None:
            for val in self.iter:
                self.list.append(val)
        print("list created :", self.list)
        return self.list


"""
目的:實現sort()四種排序類
調用方法:直接調用,並打印出運行時間


"""
class Sort():
    def __init__(self, data=None):
        self.data = data

    def __call__(self):
        return "My name is sort, my data: "

    #封裝並將其包裝爲內置調用
    def time_test(func):
        def wrapper(self, *args, **kwargs):
            time_start = time.time()
            loading = func(self, *args, **kwargs)
            time_cost = time.time() - time_start
            print(func.__name__ + " cost time : " + str((time_cost)))
            return loading

        return wrapper
    
    @classmethod
    @time_test
    def bubble_sort(self, data):         #冒泡排序
        for i in range(len(data) - 1):
            for j in range(len(data) - 1 - i):
                if data[j] > data[j + 1]:
                    data[j], data[j + 1] = data[j + 1], data[j]
        return data

    @classmethod
    @time_test
    def insert_sort(self, data):         #插入排序
        for i in range(1, len(data)): 
            insert_value = data[i]
            j = i
            while j > 0 and data[j - 1] > insert_value:
                data[j] = data[j - 1]
                j -= 1
            data[j] = insert_value
        return data

    @classmethod
    @time_test
    def selection_sort(self, data):       #選擇排序
        for i in range(0, len(data)):
            for j in range(i, len(data)):
                if data[i] > data[j]:
                    data[i], data[j] = data[j], data[i]
        return data

    @classmethod
    def sub_sort(cls, low, high, data):   #快速排序分部一
        key = data[low]
        while low < high:
            while low < high and data[high] >= key:
                high -= 1
            data[low] = data[high]
            while low < high and data[low] < key:
                low += 1
            data[high] = data[low]
        data[low] = key
        return low

    @classmethod
    def quick_sort_step(cls, low, high, data):  # #快排分部二
        # low: the first element index
        # high: the end element index

        if low < high:
            key = cls.sub_sort(low, high, data)
            cls.quick_sort_step(low, key - 1, data)
            cls.quick_sort_step(key + 1, high, data)
        return data

    @classmethod
    @time_test
    def quick_sort(cls, low, high, data):       #供調用的方法,防止裝飾器重複打印
        list = cls.quick_sort_step(low, high, data)
        return list

if __name__ == "__main__":
    list = Rand_Iter(0, 160000, 30000).get_list()    #生成30000個數字進行測試
    print('\n')
    print(Sort.selection_sort(copy.deepcopy(list)))  

    print(Sort.bubble_sort(copy.deepcopy(list)))

    print(Sort.insert_sort(copy.deepcopy(list)))

    print(Sort.quick_sort(0, len(copy.deepcopy(list)) - 1, copy.deepcopy(list)))

三、效率與穩定性測試

在生成3萬個數據,且重複率低的情況下,測試結果(排序功能均正常,由於篇幅不展示)

selection_sort cost time : 39.127073764801025
bubble_sort cost time : 62.77434682846069
insert_sort cost time : 29.311200857162476
quick_sort cost time : 0.06635117530822754

由此可見,在數據較爲龐大且重複率不高的情況下,冒泡排序效率最低,選擇排序比冒泡排序提升37%,插入排序比選擇提升25%,快速排序速度最快,並且遠遠超過前面三種排序方法。

將生成器改生成10個數據進行測試,其中重複率很低的情況下

  list = Rand_Iter(0, 100, 10).get_list()

測試結果爲插入排序速度最快, 冒泡次之,而快速排序竟然是速度最慢的。


selection_sort cost time : 1.0251998901367188e-05
[8, 40, 47, 64, 80, 81, 82, 84, 91, 96]
bubble_sort cost time : 9.298324584960938e-06
[8, 40, 47, 64, 80, 81, 82, 84, 91, 96]
insert_sort cost time : 5.0067901611328125e-06
[8, 40, 47, 64, 80, 81, 82, 84, 91, 96]
quick_sort cost time : 1.239776611328125e-05
[8, 40, 47, 64, 80, 81, 82, 84, 91, 96]

Process finished with exit code 0

 

將生成器改生成30個數字進行測試,且其中重複率很高的情況下

 list = Rand_Iter(0, 10, 30).get_list()

結果卻不一樣了,插入排序速度最快,選擇次之,快速排第三,最慢的是冒泡排序

list created : [8, 3, 10, 6, 10, 4, 3, 6, 9, 3, 8, 2, 7, 8, 8, 7, 2, 8, 3, 7, 4, 10, 8, 10, 7, 10, 6, 6, 2, 5]


selection_sort cost time : 3.314018249511719e-05
[2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 10, 10, 10, 10, 10]
bubble_sort cost time : 4.673004150390625e-05
[2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 10, 10, 10, 10, 10]
insert_sort cost time : 2.5033950805664062e-05
[2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 10, 10, 10, 10, 10]
quick_sort cost time : 3.337860107421875e-05
[2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 10, 10, 10, 10, 10]

Process finished with exit code 0

 由此可見,在數據量不龐大的情況下,四種排序差別不大,冒泡/選擇適合數據量小或重複率高的數據,而當數據量巨大時,插入排序上與兩種排序比有效率優勢,而數據量巨大的情況下最快的方法仍然是快速排序,但由於快速排序是遞歸實現的,如果數據量真的特別龐大時,其遞歸深度將會很變得很深,這可能導致與python本身限制產生衝突。

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