《python演算法筆記》(二)基礎知識
1.計算機的核心概念
- 圖靈論文《論數字計算在決斷難題中的應用》是現代電腦科學的基石。他提出的圖靈機概念成為了計算機理論的核心概念。
- 圖靈機(Turing machine):A Turing machine is a simple
(abstract) device that can read from, write to, and move along an infinitely long strip of paper 實際中的機器有所不同,但都叫做有限狀態機(finite state machine).
有限狀態機(finite state machine):it has a finite set of states (some
of which indicate that it has finished), and every symbol it reads potentially triggers reading and/or
writing and switching to a different state. You can think of this machinery as a set of rules.
這些看似簡單的機器完全的概述了計算機的本質。演算法(Algorithm):An algorithm is a procedure, consisting of a finite set of steps (possibly including loops and
conditionals) that solves a given problem in finite time.- 圖靈機就是一種模型,準確的描述演算法解決問題的過程
現代計算機用儲存器塊取代了紙帶,就是我們所熟知的記憶體(Random-Access machine) - 圖靈機是一種抽象的簡化的標準單處理計算機,並有以下特點:
1.順序執行
2.標準的基礎操作(例如算數,比較和記憶體存取)花費常量時間。
3.計算機位元組(常量時間能夠處理的值得大小)並不是無限制的。
決斷難題(Entscheidungsproblem):David Hilbert提出的問題,是否存在一個演算法來判斷數學陳述的正確性
2.漸進符號
- O:上界
- Ω:下界
- Θ:上下綜合
漸進時間複雜度的常見例子
複雜度 | 名稱 | 例子 |
---|---|---|
常量時 | 雜湊表的查詢修改 | |
對數 | 二插樹搜尋 | |
線性 | 便利列表 | |
對數線性 | 最佳排序演算法 | |
二次方 | n個物件相互比較 | |
三次方 | floyd-warshall最短路徑演算法 | |
多項式 | k層巢狀迴圈 | |
指數 | 處理n個元素的每個子集(k=2) | |
結成 | 處理n個值的每個順序 |
三種重要的情況
1.最佳情況:
2.最壞情況
3.平均情況
演算法設計的目的是獲得低的漸進執行時間(設計高效的演算法),演算法工程的目的是減少那個漸進複雜度下的隱藏的常量。
1.先用直接發解決問題,在考慮優化演算法。
2.使用
timeit
來計算時間 3.用分析工具來發現瓶頸
4.畫下你的結果
5.在你以執行時間比較為基礎做出結論時要當心隨機誤差。
for else
結構富國迴圈沒有過早的被break終止,則執行else
的子句
3.實現圖和樹
3.1圖的實現(臨接表/臨接矩陣)
2-1 A Straightforward Adjacency Set Representation
a, b, c, d, e, f, g, h = range(8)
N = [
{b, c, d, e, f}, # a
{c, e}, # b
{d}, # c
{e}, # d
{f}, # e
{c, g, h}, # f
{f, h}, # g
{f, g} # h
]
2-2 Adjacency Lists
a, b, c, d, e, f, g, h = range(8)
N = [
[b, c, d, e, f], # a
[c, e], # b
[d], # c
[e], # d
[f], # e
[c, g, h], # f
[f, h], # g
[f, g] # h
]
2-3 Adjacency dicts with Edge Weights
a, b, c, d, e, f, g, h = range(8)
N = [
{b:2, c:1, d:3, e:9, f:4}, # a
{c:4, e:3}, # b
{d:8}, # c
{e:7}, # d
{f:5}, # e
{c:2, g:2, h:2}, # f
{f:1, h:6}, # g
{f:9, g:8} # h
]
2-4 Dict with Adjacency Sets
N = {
'a':set('bcdef'),
'b':set('ce'),
'c':set('d'),
'd':set('e'),
'e':set('f'),
'f':set('cgh'),
'g':set('fh'),
'h':set('fg'),
}
2-5 An Adjacency Matrix, Implemented with Nested Lists
a, b, c, d, e, f, g, h = range(8)
# a b c d e f g h
N = [[0,1,1,1,1,1,0,0], # a
[0,0,1,0,1,0,0,0], # b
[0,0,0,1,0,0,0,0], # c
[0,0,0,0,1,0,0,0], # d
[0,0,0,0,0,1,0,0], # e
[0,0,1,0,0,0,1,1], # f
[0,0,0,0,0,1,0,1], # g
[0,0,0,0,0,1,1,0]] # h
2-6 A Weight Matrix with Infinite Weight for Missing Edges
a, b, c, d, e, f, g, h = range(8)
_ = float('inf')
# a b c d e f g h
W = [[0,2,1,3,9,4,_,_], # a
[_,0,4,_,3,_,_,_], # b
[_,_,0,8,_,_,_,_], # c
[_,_,_,0,7,_,_,_], # d
[_,_,_,_,0,5,_,_], # e
[_,_,2,_,_,0,2,2], # f
[_,_,_,_,_,1,0,6], # g
[_,_,_,_,_,9,8,0]] # h
3.2樹的實現
2-7 A Binary Class
class Tree:
def __init__(self, left, right):
self.left = left
self.right = right
>>> t = Tree(Tree("a", "b"), Tree("c", "d"))
>>> t.right.left
'c'
2-8 A Multiway Tree Class
class Tree:
def __init__(self, kids, next=None):
self.kids = self.val = kids
self.next = next
>>> t = Tree(Tree("a", Tree("b", Tree("c", Tree("d")))))
>>> t.kids.next.next.val
'c'
Bunch Pattern(一個靈活的類,允許你在構造器中制定任一屬性)
class Bunch(dict):
def __init__(self, *args, **kwds):
super(Bunch, self).__init__(*args, **kwds)
self.__dict__ = self
>>> T = Bunch
>>> t = T(left=T(left="a", right="b"), right=T(left="c"))
>>> t.left
{'right': 'b', 'left': 'a'}
>>> t.left.right
'b'
>>> t['left']['right']
'b'
>>> "left" in t.right
True
>>> "right" in t.right
False
3.3圖和樹還有其他表示方法,具體的實現要結合具體的問題
雜湊:為任意一個物件計算出一個整數
4.小心黑盒子(底層實現)
如果不知道底層實現可能會增加演算法的時間複雜度。
例如:
1.check in list and set
>>> from random import randrange
>>> L = [randrange(10000) for i in range(1000)]
>>> 42 in L
False
>>> S = set(L)
>>> 42 in S
False
由於list其實是array,所以對list進行check的時間複雜度是線性的,set是經過雜湊的,所以對lset進行check的時間複雜度是常量時間。
2.構造字串
>>> s = ""
>>> for chunk in input():
...
s += chunk
它起作用,因為在python中做了一些聰明的優化,但是如果到達一定的大小,優化就會崩塌,時間複雜度就會上升到二次方。每一次+=
操作都會建立一個新的字串。一個更好的方法是:
>>> chunks = []
>>> for chunk in input():
...
chunks.append(chunk)
...
>>> s = ''.join(chunks)
更進一步的簡化
>>> s = ''.join(input())
3.Floats的麻煩
float
的精度不高,在要求高精度的情況下請用decimal