1. 程式人生 > 其它 >資料結構與演算法 1.複雜度

資料結構與演算法 1.複雜度

複雜度


1.演算法的評估

如果單從執行效率上進行評估,可以比較不同演算法對同一組資料的的執行處理時間
但此方法執行時間嚴重依賴硬體以及執行時各種不確定的環境因素,測試資料的選擇也比較難確保公正

一般從以下維度來評估演算法:
    正確性、可讀性、健壯性(對不合理輸入的反應能力和處理能力)
    時間複雜度:估算程式指令的執行次數(執行時間)
    空間複雜度:估算需要佔用的儲存空間

演算法的優化方向
    用盡量少的儲存空間
    用盡量少的執行步驟(執行時間)
    根據情況可以用時間換空間,或用空間換時間

2. O 表示法

一般用O來描述複雜度,它表示的是資料規模n對應的複雜度
忽略常數、係數、低階
Big O 表示法僅僅是一種粗略的模型分析,是一種估算

常見的複雜度
    100                        O(1)            常數階
    xlog2(n) + x               O(logn)         對數階
    xn + x                     O(n)            線性階
    xn + xnlog2(n) + x         O(nlogn)        n倍對數階
    xn^2 + xn +x               O(n^2)          平方階
    xn^3 + xn^2 + xn +x        O(n^3)          立方階
    x^n                        O(x^n)          指數階
    
O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(x^n) < O(n!) < O(n^n)

3.複雜度的估算

O(1)
def test1(n):
    # 1 + 30  =>  O(1)
    # 1
    if n < 3 :
        print('n < 3')
    elif n > 3 and n < 7 :
        print('3 < n < 7')
    elif n > 7 :
        print('n > 7')
    # 3*10
    for i in range(10):
        print('test')
O(n)
def test2(n):
    # 1 + 3n  =>  O(n)
    # 1
    i = 0
    # 3*n
    for i in range(n) :
        print('test')

def test3(n):
    # 1 + 2n + n(1+60)  =>  1 + 63n  =>  O(n)
    # 1
    i = 0
    # 2*n
    for i in range(n):
        # n*(1+3*20)
        j = 0
        for j in range(20):
            print('test')
O(n^2)
def test4(n):
    # 1 + 2n + n(1+3n)  =>  1 + 3n + 3n^2  =>  O(n^2)
    # 1
    i = 0
    # 2*n
    for i in range(n):
        # n*(1+3n)
        j = 0
        for j in range(n):
            print('test')
O(logn)
def test5(n):
    # x = log2n  =>  O(logn)
    # 2^x = n
    while n // 2 > 0 :
        n = n // 2
        print('test')
O(nlogn)
def test6(n):
    # 1 + 2log2(n/i) + log2(n/i)(1 + 3n)  =>  1 + 3log2(n/i) + 3nlog2(n/i)  =>  O(nlogn)
    # 1
    i = 1
    # i*2^x = n  =>  x = log2(n/i)
    # 2x
    while i < n :
        i += i
        # x*(1 + 3n)
        j = 0
        for j in range(n) :
            print('test')

斐波那契數列複雜度

(1) 遞迴
t1 = time.time()
def fib1(n):
    if n == 1 :
        return 0
    elif n == 2 :
        return 1
    else :
        return fib1(n-1) + fib1(n-2)
res = fib1(32)
print(res)
t1_end = time.time()
T1 = t1_end - t1
print(T1)

1346269
1.1563451290130615
(2) 算術方法
t2 = time.time()
def fib2(n):
    i,n1,n2 = 0,0,1
    if n == 1:
        return 0
    elif n == 2:
        return 1

    while i < n - 2 :
        s = n1 + n2
        n1 = n2
        n2 = s
        i += 1
    return s
res = fib2(32)
print(res)
t2_end = time.time()
T2 = t2_end - t2
print(T2)

1346269
0.0