python 冒泡排序,插入排序,歸併排序,快速排序實現code

 
import time
import random

time.clock()

class BubbleSort(object):
    """冒泡排序算法"""
    def sort_inc(self, nums):
        """若是數組長度爲n,那麼時間複雜度:
        一共比較n-1次,
        第X次     比較次數
        1           n-1
        2           n-2
        ...
        n-1         1
        時間複雜度爲比較次數的和:1 + 2 + 3 + 。。。。 + n-1 = n(n-1)/2
        複雜度去除常數和低階項,結果是O(n^2)
        """
        length = len(nums)
        if length == 1:
            return nums
        for i in range(length-1):
            for j in range(i+1, length):
                if nums[i] > nums[j]:
                    nums[i], nums[j] = nums[j], nums[i]
        return nums


class InsertSort(object):
    """插入排序算法"""
    def sort_inc(self, nums):
        """若是數組長度爲n,那麼時間複雜度:
        一共比較n-1次,數組元素從1 -> n-1
        第X次     比較次數
        1           <=1
        2           <=2
        ...
        n-1         <= n-1
        時間複雜度爲比較次數的和:1 + 2 + 3 + 。。。。 + n-1 = n(n-1)/2
        複雜度去除常數和低階項,結果是O(n^2)"""
        length = len(nums)
        if length == 1:
            return nums
        for i in range(1, length):
            key = nums[i]
            for j in range(i-1, -1, -1):
                if key < nums[j]:
                    nums[j+1] = nums[j]
                else:
                    nums[j+1] = key
                    break  # 從這裏退出循環是不會執行下面的else的
            else:  # 不是從break退出的,因此全部的數字都比key大,key應該放在第一個
                nums[0] = key
        return nums


class MergeSort(object):
    """合併排序"""
    def sort_inc(self, nums):
        length = len(nums)
        if length == 1:
            return nums

        sorted_num1 = self.sort_inc(nums[:length >> 1])
        sorted_num2 = self.sort_inc(nums[length >> 1:])

        # 將1和2排序
        length1 = len(sorted_num1)
        length2 = len(sorted_num2)
        l1 = 0
        l2 = 0
        ret = []
        while True:
            if l1 < length1 and l2 < length2:
                if sorted_num1[l1] < sorted_num2[l2]:
                    ret.append(sorted_num1[l1])
                    l1 += 1
                else:
                    ret.append(sorted_num2[l2])
                    l2 += 1
            elif l1 == length1:
                ret += sorted_num2[l2:]
                break
            elif l2 == length2:
                ret += sorted_num1[l1:]
                break
            else:
                print("ERROR: l1 = %d, l2 = %d" % (l1, l2))
                exit(-1)
        return ret


class FastSort(object):
    def sort_inc(self, nums, left, right):
        if left >= right:
            return

        key = nums[left]  # 記錄基準值
        keng = left  # 記錄坑的索引值
        i = left
        j = right

        # 填坑,退出循環時i = j = keng
        while i < j:
            # 從右往左找小值
            while i < j:
                if nums[j] < key:  # 找到小值拿去填坑,將坑至於當前位子
                    nums[keng] = nums[j]
                    keng = j
                    break
                j -= 1

            # # 從左往右找大值
            while i < j:
                if nums[i] > key:
                    nums[keng] = nums[i]
                    keng = i
                    break
                i += 1

        # 坑填完後,把key填到坑裏
        nums[keng] = key
        self.sort_inc(nums, left, keng-1)
        self.sort_inc(nums, keng+1, right)

        return nums


def test_func(className, *args):
    test = className()
    begin = time.clock()
    ret = test.sort_inc(*args)
    end = time.clock()
    cost_time = end - begin
    print(str(className) + "running time:\t", cost_time)
    return ret, cost_time


mt = 0
ft = 0
it = 0
bt = 0

# 是否測試
isMergeSort, isFastSort, isInsertSort, isBubbleSort = True,  True,  False, False

test_count = 1000  # 測試次數
data_length = 10000  # 生成測試數據個數

for x in range(test_count):
    # random test data
    testlist = []
    for i in range(data_length):
        testlist.append(random.randint(1, 1000000))  # 測試數據範圍

    # test part       #############################################
    if isMergeSort:
        l1, t1 = test_func(MergeSort, testlist.copy())
        mt += t1

    if isFastSort:
        l2, t2 = test_func(FastSort, testlist.copy(), 0, len(testlist) - 1)
        ft += t2

    if isInsertSort:
        l3, t3 = test_func(InsertSort, testlist.copy())
        it += t3

    if isBubbleSort:
        l4, t4 = test_func(BubbleSort, testlist.copy())
        bt += t4

print("test %d times, data length is %d" % (test_count, data_length))
if isMergeSort:
    print("MergeSort:\t", t1 / test_count)

if isFastSort:
    print("FastSort:\t", t2 / test_count)

if isInsertSort:
    print("InsertSort:\t", t3 / test_count)

if isBubbleSort:
    print("BubbleSort:\t", t4/test_count)

 

時間複雜度:html

冒泡排序:算法

  1+2+。。。+n-1 ~ n2/2數組

插入排序:app

  最優:以及排序好的數組:n-1dom

  最差:逆序數組:和冒泡同樣,1+2+。。。+n-1 ~ n2/2測試

歸併排序:spa

  本身些的分析見下面的文章,時間複雜度:nlogncode

  https://www.cnblogs.com/gsp1004/p/10825941.htmlhtm

  多說一句,我最開始覺得空間複雜度是nlogn。但實際是nblog

  個人錯誤理解:按照樹展開,每層有n個元素,一共logn層,可是並非這樣的,

  正確的順序的:歸併排序的遞歸會先將樹從左子節點一直執行到最底部的葉子節點,因此空間複雜度:n/2 + n/4 + n/8 + ... + 1 ~ n

快速排序:

  快排的時間複雜度到底怎麼算的如今仍是木有搞懂,由於最優就變成了相似歸併O(nlogn),最差就變成了相似冒泡O(n2),可是說什麼平均時間複雜度是O(nlogn)。。。這個待研究。

  可是快排是原地排序,不須要開闢新的內存,也就是空間複雜度是0

 

本身測試的這幾個排序的時間:

  插入和冒泡是一個量級,可是插入快一些。可是數據量大了後,就真的弱爆了。看下面1w數據執行時間對比就知道了。可是數據量小的時候,好比就幾十個(30個之內?),差別不大,貌似用插入會更快一點點~~~

  快排和歸併是一個量級,可是快排要快一些。這一點我很費解,爲何快排會快一些???有一個坑要研究一會兒。。。

 

100w數據:

<class '__main__.MergeSort'>running time: 6.76003047388366

<class '__main__.FastSort'>running time: 5.620691225466125

 

10w數據:

<class '__main__.MergeSort'>running time: 0.5305758325035888

<class '__main__.FastSort'>running time: 0.4379082312716691

 

1w數據:

<class '__main__.MergeSort'>running time: 0.049988164087996834

<class '__main__.FastSort'>running time: 0.032162911379993483

<class '__main__.InsertSort'>running time: 3.9088220416271278

<class '__main__.BubbleSort'>running time: 6.644870537276558

 

1w數據跑1k次:

test 1000 times, data length is 10000

MergeSort: 3.865276552134844e-05

FastSort: 2.9817472595865978e-05

 

test 1000 times, data length is 10000

MergeSort: 3.639758325856235e-05

FastSort: 2.8445983728389024e-05

相關文章
相關標籤/搜索