###### tags: `資訊科技`
# 資料結構與演算法(使用Python、ZeroJudge)
## 零、學習資料結構與演算法的目的
### 1. 資料結構討論「資料儲存的方式」
+ 如陣列、鏈結串列
### 2. 演算法討論「解決問題的想法」
+ 如排序方法、找質數的方法
:mega: 所選用的資料結構和演算法將影響程式的複雜度與效率
### 3.參考網站
+ [演算法與資料結構](http://alrightchiu.github.io/SecondRound/mu-lu-yan-suan-fa-yu-zi-liao-jie-gou.html)
+ [Algorithms and Data Structures](http://gousios.org/courses/algo-ds/)
<br />
## 一、資料結構
### 1. 堆疊
+ LIFO(last in first out)
+ 串列模擬堆疊(Stack)常用的方法
| 串列方法(函式) | 意義 |
|:-----|:----------|
| len(sk) | 回傳串列個數 |
| sk.append(x) | 將 x 附加到串列後面 |
| sk.pop() | 回傳最後一個元素並刪除 |
+ [模擬程式](https://www.cs.usfca.edu/~galles/visualization/StackArray.html)
:::info
EX_1_1:執行下列堆疊程式,印出一堆堆疊操作後的堆疊內容。
:::
``` python=
sk = [] # 以list模擬
sk.append(5)
sk.append(3)
sk.pop()
sk.append(7)
sk.pop()
sk.append(4)
while ~ : # 堆疊不空
~ # 印出堆疊最上面的元素
~ # pop掉這個元素
```
<br />
### 2. 佇列
+ FIFO(first in first out)
+ 串列模擬佇列(Queue)常用的方法
| 串列方法(函式) | 意義 |
|:--------|:----------|
| len(q) | 回傳串列個數 |
| q.append(x) | 將 x 附加到串列後面 |
| q.pop(i) | 回傳索引值i的元素,並將其刪除;<br/>如果沒有i,則傳回最後一個元素並刪除 |
+ [模擬程式](https://www.cs.usfca.edu/~galles/JavascriptVisual/QueueArray.html)
:::info
EX_1_2:執行下列佇列程式,印出一堆佇列操作後的佇列內容。
:::
``` python=
q = []
q.append(5)
q.append(3)
q.pop(0)
q.append(7)
q.pop(0)
q.append(4)
while ~ : # 佇列不空
~ # 印出佇列前面的元素
~ # pop掉這個元素
```
<br />
### 3. 樹
+ [模擬具有樹枝狀性質的資料](http://web.ntnu.edu.tw/~algo/Tree.html),由節點與邊組成,例如家族族譜、電腦資料夾結構。
![](https://i.imgur.com/sbgxlao.png =100x)
+ [二元樹](https://mark-lin.com/posts/20170309/#--binary-tree-)
+ [二元樹的走訪(Tree Traversal)](http://alrightchiu.github.io/SecondRound/binary-tree-traversalxun-fang.html#pre)(課本p4-7)
- [前序走訪(preOrder):先走訪樹根,然後左子樹,最後右子樹。](https://www.youtube.com/watch?v=jKUqfFgMatQ)
- [中序走訪(inOrder):先走訪左子樹,然後樹根,最後右子樹。](https://www.youtube.com/watch?v=PQUUzrvV-7M)
- [後序走訪(postOrder):先走訪左子樹,然後右子樹,最後樹根。](https://www.youtube.com/watch?v=_slTRpD1tIE)
<br/>
:::info
EX_1_3:下圖的前序、中序、後序走訪分別為?
![](https://i.imgur.com/rzMHnHj.png =450x)
:::
+ [二元搜尋樹](https://mark-lin.com/posts/20170309/#--binarysearch-tree-)(課本p4-12)
- [模擬程式](https://visualgo.net/en/bst)
:::info
EX_1_4:建立二元搜尋樹
依讀入順序 30, 15, 50, 35, 10, 25, 40, 20, 45 建立一個二元搜尋樹(binary search tree)。
:::
+ 樹的應用
- [遊戲樹(game tree)](https://commons.wikimedia.org/wiki/File:Tic-tac-toe-full-game-tree-x-rational.jpg)(課本p4-20)
- [霍夫曼編碼(Huffman Coding)](http://puremonkey2010.blogspot.com/2011/02/huffman-code.html)(課本p4-24)
:::info
EX_1_5:若一篇文章每個字母出現的次數為:a:8,b:7,c:3,d:4,e:5。
建立Huffman Tree(次數小的結點放左邊),並求每個字母的Huffman Code。
a->11
b->
c->
d->
e->00
:::
<br />
### 4. 圖
+ [圖形是「頂點」(vertex)和邊(edge)所組成](https://mark-lin.com/posts/20170311/)
+ 圖常用的表示法
- [相鄰矩陣表示法(Adjacency Matrix)](http://web.ntnu.edu.tw/~algo/Graph.html#3)(課本p5-10)
- [相鄰串列表示法(Adjacency Lists)](http://web.ntnu.edu.tw/~algo/Graph.html#4)
+ 圖的搜尋(課本p5-12)
- [深度優先搜尋(Depth First Search,DFS)](https://jason-chen-1992.weebly.com/home/-graph-searching-methods):以堆疊(Stack)、遞迴來實作。(類似樹的前序走訪)
* [模擬程式1](https://visualgo.net/en/dfsbfs?slide=1)
* [模擬程式2](https://www.cs.usfca.edu/~galles/visualization/DFS.html)
* [Animation of Graph DFS](https://www.youtube.com/watch?v=NUgMa5coCoE)
- [廣度優先搜尋(Breadth First Search,BFS)](http://simonsays-tw.com/web/DFS-BFS/BreadthFirstSearch.html):以佇列(Queue)來實作。
* [模擬程式1](https://visualgo.net/en/dfsbfs?slide=1)
* [模擬程式2](https://www.cs.usfca.edu/~galles/visualization/BFS.html)
* [Animation of Graph BFS](https://www.youtube.com/watch?v=x-VTfcmrLEQ)
:::info
EX_1_6:[下圖的DFS與BFS走訪順序為(子節點以字母序走訪)](https://docs.google.com/drawings/d/1WHsqYwHsgG8ILC-MXCpo6S_oZ_5LdhjZ25-PAldwXkA/edit?usp=sharing)?
![](https://i.imgur.com/0NMKz8g.png =460x)
DFS: 將走訪順序標示在字母「上」。
線條以「黑色箭頭」代表往下探尋,以「白色箭頭」代表回溯上一個點。
BFS: 將階層編號(紅色)標示在字母「下」。
:::
+ 圖的應用1-[最小生成樹(minimum spanning tree)](https://www.itread01.com/content/1545066724.html)(課本p5-23)
- Kruskal演算法為一個使用貪婪法 (greedy method) 的演算法,一開始為一空樹,每次在不讓圖中含有任何迴路(cycle)下尋找圖中最小權重的邊加入樹中,直到所有點皆在樹中即完成。
- Prim演算法與Dijkstra演算法類似,屢次找出不在樹上,離樹最近的點。
:::info
EX_1_7:畫出下圖的最小生成樹,其權重總和為?++**28**++
![](https://i.imgur.com/tjw9GuN.png =350x)
:::
+ 圖的應用2-[最短路徑(一個頂點到多頂點Dijkstra)](http://puremonkey2010.blogspot.com/2013/05/alg-info-dijkstras-algorithm-shortest.html)(課本p6-20)
:::info
EX_1_8:畫出下圖的相鄰陣列,以Dijkstra演算法,求A到各點的最短路徑(以Excel表格表示)?++**0 8 6 4 3 1 5**++
![](https://i.imgur.com/f0wz9DD.jpg =270x)
:::
<br />
## 二、演算法
### 1. 演算法效能
+ [運算能力](https://buzzorange.com/techorange/2019/09/11/solve-sums-of-three-cubes/)
- 費式數列-遞迴 vs. 陣列
- 搜尋-循序 vs. [二分搜尋](https://www.cs.usfca.edu/~galles/visualization/Search.html)
+ [時間複雜度](https://jason-chen-1992.weebly.com/home/time-space-complexity)
- [常見的六種時間複雜度與演算法](https://medium.com/appworks-school/%E5%88%9D%E5%AD%B8%E8%80%85%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-%E5%BE%9E%E6%99%82%E9%96%93%E8%A4%87%E9%9B%9C%E5%BA%A6%E8%AA%8D%E8%AD%98%E5%B8%B8%E8%A6%8B%E6%BC%94%E7%AE%97%E6%B3%95-%E4%B8%80-b46fece65ba5)
+ 大O記號(Big-O notation)
- 令f(n) 與g(n) 是由非負整數對應至實數的函數,若存在正實數常數c 和正整數常數n~0~,使n≧n~0~時,f(n) ≦ cg(n) 成立,則我們說 f(n)=O(g(n))。
- 若f(n)=3n^2^+2,g(n)=n^2^ (n~0~=2, c=4)。f(n)=O(n^2^)
![](https://i.imgur.com/iXNlfVN.png =300x)
<br />
### 2.求質數演算法效能比較
:::info
EX_2_1:[d237: 質數合](https://zerojudge.tw/ShowProblem?problemid=d237)
以『[埃拉托斯特尼篩法](https://zh.wikipedia.org/wiki/%E5%9F%83%E6%8B%89%E6%89%98%E6%96%AF%E7%89%B9%E5%B0%BC%E7%AD%9B%E6%B3%95)』讓本題的速度更快。
:::
``` python=
n = 2000000
prime = [True]*(n+1) # 產生n+1個True的list
for i in range(2, int(n**0.5)+1) : # 檢查到<=√n即可
if ~ : # 如果i是質數
for j in range(~, n+1, ~) : # 如果i是質數,則篩掉它的倍數。(從i^2開始,每次+i)
prime[~] = ~ # i的倍數不為質數
lst = [x for x in range(2, n+1) if prime[x]]
print(sum(lst))
```
### 3. 排序(sort)
+ [思考排序的演算法(1)](https://zh.wikipedia.org/wiki/十三張) [(2)](https://kopu.chat/2017/06/22/插入排序insertion-sort/)
+ [模擬程式](https://visualgo.net/en/sorting?slide=1)
+ [Bubble Sort](https://medium.com/@mingjunlu/understanding-bubble-sort-7aa4567986ae)
+ [Sorting Algorithms Animations](https://www.toptal.com/developers/sorting-algorithms)
:::info
EX_2_2:練習 bubble sort
:::
``` python=
a=[6,4,9,8,3]
for ~ : # 5 個數字排序只需 4 個循環
for ~ : # 每次兩兩比較,每次比較索引值「0、1」「1、2」「2、3」「3、4」 的數字
if a[~]>a[~] : # 如果左邊比右邊大
~ # a[j]和a[j+1]交換
Q:for 內圈寫完後(將最大值移至最右的位子),複製貼上5次,程式碼會正確嗎?
```
### 4. 二分搜尋(binary search)
+ [模擬程式](https://www.cs.usfca.edu/~galles/visualization/Search.html)
### 5. 分而治之(Divid and Conquer)
+ [合併排序(Merge Sort)1](https://medium.com/appworks-school/%E5%88%9D%E5%AD%B8%E8%80%85%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-%E6%8E%92%E5%BA%8F%E6%B3%95%E9%80%B2%E9%9A%8E-%E5%90%88%E4%BD%B5%E6%8E%92%E5%BA%8F%E6%B3%95-6252651c6f7e)、[合併排序2](http://alrightchiu.github.io/SecondRound/comparison-sort-merge-sorthe-bing-pai-xu-fa.html)