什麼是數據結構
對於什麼是數據結構至今都沒有統一的定義。我們日常中處理不同的數據,做法也不一樣。假設我們是圖書管理員,需要整理一堆書,整理起來還需要考慮以後查找方便。你可能會想到按照字母順序排放,但是以後查找起來還是會比較麻煩要按照拼音順序進行二分查找。此時插入新書還是會比較困難,如果是一本字母A開頭的,想要插入進去,那麼之後的書籍都需要往後挪一下,比較複雜。
另一種方法就是我們現實生活中採取的辦法,把書架劃分成幾塊區域,每塊區域指定擺放某種類別圖書,在每種類別內,按照書名的拼音字母順序排放。此時,插入的時候就先定類別,用二分查找確定位置,移出空位。找指定數目也是,先定類別,再二分查找。此時也存在問題: 空間怎麼分配,各種類別分配需要多細。
循環與遞歸
對於循環和遞歸,寫了一個可以對比在迭代相同次數所耗費時間的代碼,感興趣的可以自己跑一下試試,改變number
數據的大小,就會發現遞歸所耗費的空間是非常巨大的。
import time
import numpy as np
import matplotlib.pyplot as plt
number = np.arange(10, 1000, 10)
print(number)
def computer_time_1(number):
cost_time = []
for j in number:
start_time = time.time()
for i in range(j+1):
print (i)
end_time = time.time()
cost = end_time - start_time
cost_time.append(cost)
return cost_time
def Print(N):
if N != 0:
Print(N - 1)
print(N)
return None
def computer_time_2(number):
cost_time = []
for i in number:
start_time = time.time()
Print(i)
end_time = time.time()
cost = end_time - start_time
cost_time.append(cost)
return cost_time
cost_1 = computer_time_1(number)
cost_2 = computer_time_2(number)
plt.plot(number, cost_1,label='For')
plt.plot(number, cost_2,label='recursive')
plt.show()
擬合二項式
寫程序計算給定如下多項式在給定點處的值:
如果用for
循環實現的話,可以大體表示爲如下形式:
n =3
f_x = 0
x = 1
a = [1,2,3]
for i in range(n):
f_x = f_x + a[i]*pow(x,i)
print (f_x)
但是上述的寫法據陳越奶奶說,會被專業程序員鄙視。而應該先把上述公式用乘法結合律改寫爲如下形式:
那麼計算的時候就是先算最後那一項, 然後將其作爲與相乘再加上一個係數就可以。
n =1
f_x = 0
x = 1
a = [1,2,3]
for i in reversed(range(n)):
f_x = a[i] + x * f_x
print (f_x)
那上述兩種方法的區別在哪裏呢?可以看到兩種方法都是用for
循環做的,但是for
循環裏面所用的乘法不一樣,第一種方法用了次乘法。第二種方法用了次乘法。因此第一個算法的時間複雜度,第二種算法的時間複雜度。當很大的時候,第一個程序就會跑地比第二個程序慢很多。
抽象數據類型
抽象數據類型需要分清楚兩個概念:抽象、數據類型。數據類型一個是數據本身,另一個是對數據的操作。單純的數據沒有意義,跟操作結合起來才能實現功能。
什麼是算法
算法(Algorithm
)主要會滿足以下五個點
- 一個有限指令集。
- 接受- -些輸入(有些情況下不需要輸入)。
- 產生輸出。
- 一定在有限步驟之後終止。
- 每一條指令必須有充分明確的目標,不可以有歧義計算機能處理的範圍之內描述應不依賴於任何一種計算機語言以及具體的實現手段。
什麼是好的算法
實現一種問題的算法不止一種,那什麼是好的算法呢?好的算法時間複雜度和空間複雜度都需要比較低。
- 時間複雜度:
根據算法寫成的程序在執行時耗費時間的長度。這個長度往往也與輸入數據的規模有關。時間複雜度過高的低效算法可能導致我們在有生之年都等不到運行結果。
- 空間複雜度:
根據算法寫成的程序在執行時佔用存儲單元的長度。這個長度往往與輸入數據的規模有關。空間複雜度過高的算法可能導致使用的內存超限,造成程序非正常中斷。