``` 112考資工研究所時寫的筆記,有錯歡迎留言指正 內文有引用他人筆記/教材/文章的地方 若有侵權十分抱歉,告知後將立刻撤除 ``` [TOC] # Basic concept - 太基本了,幾乎都是algo的東西,skip # Array - 算幾題array和位址的轉換(2d array很多陷阱)就差不多了 - row major 和 column major 算出來結果可能都可以,答案就會不只一個 # Stack & Queue - queue & stack的實作應該可以跳過 (算都會了吧?) - 考過不只一次,不看根本不會 - [infix to prefix using stack](https://www.youtube.com/watch?v=8QxlrRws9OI) - [infix to postfix using stack](https://www.youtube.com/watch?v=PAceaOSnxQs) - postfix 用stack運算結果 - 歷屆16, 19 # Linked list - Sparse matrix (p141)有點常考 - Generalized list (p149) - 挺煩人的,很容易忘 # Tree & Binary Tree - Define: - $n:$全部node個數 - $n_0:$ deg(v)=0的node個數 - $n_1:$ deg(v)=1的node個數 - $n_2:$ deg(v)=2的node個數 - 重要定理$: n_0=n_2+1$ - proof: $n=n_0+n_1+n_2=1+n1+2n_2$ - 三種node合=從deg記算的node數,+1為沒被算入的root(沒人存他) - ==Complete== Binary tree - 簡單來說就是,由上到下由左到右長 - ![](https://hackmd.io/_uploads/ryNbH0T42.png =40%x) - ==Full== Binary tree - 定義一: - 剛好把leaf那層長滿,每片數葉深度都一樣 - 深度為h的full binary tree,node必為$2^h-1$ - ![](https://hackmd.io/_uploads/HJQzSApE3.png =40%x) - 定義二: - 除了葉子以外的節點 (internal node) degree皆為n (n在binary tree中為2) - ![](https://hackmd.io/_uploads/B1sfrCTE3.png =30%x) - 兩個定義的tree會長得很不一樣,需看題目怎麼定義 - 把BST用inorder輸出,即為排序好的結果 - Thread Binary Tree (p182) - 看一下線怎麼連,code先skip - Leftmost child next right sibling (p187) - 留左邊child的link,其他砍掉,同層連起來,旋轉45度 (很抽象) - 森林轉成樹 (p188) - root連在一起,旋轉一下 - Inorder, preorder, postorder熟到爛掉,skip - 記得一定要有Inorder才能決定唯一tree (preorder, postorder無法唯一決定) - n個node的binary tree有$\displaystyle \frac{1}{n+1} {2n \choose n}$種 (catalan number) - 計算某條件下(ex. deg=i的node有幾個)的internal node/leaf數量,把branch數量也拿來列式 (歷屆5,6) - Heapify整棵是亂的樹 (歷屆38) - 從root開始,廣度優先檢查node是否符合heap規則(可能是min or max當parent) - ==Heap可以在O(n)時間內建好== - ![](https://hackmd.io/_uploads/HkzrBAaEh.png) - from [mega ch5 tree](https://drive.google.com/file/d/1zoJAlbWOsHr7ZewSVKT7dPgKSDSd0ako/view?usp=share_link) - [stackoverflow說明](https://stackoverflow.com/questions/9755721/how-can-building-a-heap-be-on-time-complexity#:~:text=In%20summary%2C%20the%20work%20for,O(n%20log%20n).) - 但是把每個node刪除/提取出,還是需要$O(n\lg n)$ # Graph - edge種類(DFS後,把edge分成4種) 1. Tree: Edges in the DFS forest 2. Back: From descendant to ancestor when explored (include self loop) 3. Forward: From ancestor to descendant when explored (exclude tree edge) 4. Cross: Others (no ancestor-descendant relation) - ==無向圖只有tree edge, back edge而已!== - ![](https://hackmd.io/_uploads/BJhrSAaE2.png) - [articulation point](https://www.geeksforgeeks.org/articulation-points-or-cut-vertices-in-a-graph/) (cut vertex) - 移出該vertex後,會導致圖變為disconnected,稱作articulation point - 尋找articulation point的演算法 - Remove v from graph - See if the graph remains connected (BFS or DFS) - Add v back to the graph - ### adjacency matrix vs transitive closure - adjacency matrix對角線是0,transitive closure對角線是1 - adjacency matrix紀錄點之間的距離 - transitive closure紀錄的是"能到達為1,不能到達為0" - [AOE network](https://garychang.gitbook.io/data-structure/4-graph/4.5-aoe-network) (activity on edge network) - 以p297 試題50為例 - 先算出每個node最早發生時間,反推可得最晚發生時間,兩個時間可以註記在node上 - critial path length即為最後一個node(event)的數字 - 用看的找出critical path (看一下length是不是跟上面一樣!) - event最早完成時間就是activity的earlist start time - event最晚完成時間減去活動長度即為activity的latest start time - 我還是拍影片好了 # Sorting - 證明用comparison為基礎的排序至少都要nlgn的時間: - 說明decision tree高度為$\lceil \log_2 n! \rceil+1$ ![](https://hackmd.io/_uploads/Sy5LHR6N2.png) ![](https://hackmd.io/_uploads/HkZDSC6V2.png) ![](https://hackmd.io/_uploads/SyZOH0aEn.jpg) 穩定排序: **插入、泡泡、融合、基數** (insertion, bubble, merge, radix) 不穩定排序(也可記排除上面那些): **選擇、快速、堆積** (selection, quick, heap) ## Insertion sort 不斷把尚未sort的item插入前面已經sort好的部分 - Stable - Space complexity: $O(1)$ - Time complexity: - Worst: $O(n^2)$ - Avg: $O(n^2)$ ```cpp= void InsertionSort(int *arr, int size){ for (int i = 1; i < size; i++) { int key = arr[i]; int j = i - 1; while (key < arr[j] && j >= 0) { arr[j+1] = arr[j]; j--; } arr[j+1] = key; } } ``` 參考 [Comparison Sort: Insertion Sort(插入排序法)](http://alrightchiu.github.io/SecondRound/comparison-sort-insertion-sortcha-ru-pai-xu-fa.html) [Rust Algorithm Club](https://rust-algo.club/sorting/insertion_sort/index.html) ## Selection sort 一直把最小的抓下來放 - Unstable - Space complexity: $O(1)$ - Time complexity: - Worst: $O(n^2)$ - Avg: $O(n^2)$ ```cpp= void selection_sort(int array[], int n) { for (int i=0; i<n-1; i++) { int min_idx = i; for (int j=i+1; j<n; j++) if (array[j] < array[min_idx]) min_idx = j; swap(array, min_idx, i); } } ``` 參考 [Rust Algorithm Club](https://rust-algo.club/sorting/selection_sort/index.html) [C/C++ selection sort 選擇排序法](https://shengyu7697.github.io/cpp-selection-sort/) ## Bubble sort(sinking sort) 比較兩個相鄰元素,若首個元素比次個元素大,置換兩者的位置。 依序對相鄰元素執行步驟一,直到抵達序列頂端,此時頂端元素排序完成。 重複步驟 1 - 2 的整個序列疊代,==直到任何一次疊代沒有執行元素置換。== 當然也可以如下程式,直接疊代n次後停止 - stable - Space complexity: $O(1)$ - Time complexity: - Worst: $O(n^2)$ - Avg: $O(n^2)$ ```cpp= for(i = n-1; i > 0; i--) for(j = 0; j <= i-1; j++) if( A[j] > A[j+1]) swap(A, j, j+1); ``` 參考 [[C++] 氣泡排序法(Bubble sort)](https://medium.com/@oturngo/study-note-01-%E6%B0%A3%E6%B3%A1%E6%8E%92%E5%BA%8F%E6%B3%95-bubble-sort-ee534b6f91eb) ## Quick sort 畫sort過程必考,看講義316說明和範例很容易懂 - Unstable - Space complexity: $O(n)$ - Time complexity: - Worst: $O(n^2)$ - Avg: $O(n \log n)$ ```cpp= int Partition(int *arr, int front, int end){ int pivot = arr[end]; int i = front -1; for (int j = front; j < end; j++) { if (arr[j] < pivot) { i++; swap(&arr[i], &arr[j]); } } i++; swap(&arr[i], &arr[end]); return i; } void QuickSort(int *arr, int front, int end){ if (front < end) { int pivot = Partition(arr, front, end); QuickSort(arr, front, pivot - 1); QuickSort(arr, pivot + 1, end); } } ``` 參考 [Comparison Sort: Quick Sort(快速排序法)](http://alrightchiu.github.io/SecondRound/comparison-sort-quick-sortkuai-su-pai-xu-fa.html) ## Merge sort 合併過程必考,講義322,324分別為兩種(Iterative/Recursive)合併方法 - stable - Space complexity: $O(n)$ - Time complexity: - Worst: $O(n \log n)$ - Avg: $O(n \log n)$ ```cpp= void Merge(std::vector<int> &Array, int front, int mid, int end){ // 利用 std::vector 的constructor, // 把array[front]~array[mid]放進 LeftSub[] // 把array[mid+1]~array[end]放進 RightSub[] std::vector<int> LeftSub(Array.begin()+front, Array.begin()+mid+1), RightSub(Array.begin()+mid+1, Array.begin()+end+1); LeftSub.insert(LeftSub.end(), Max); // 在LeftSub尾端加入Max元素(sentinel) RightSub.insert(RightSub.end(), Max);// 在RightSub尾端加入Max元素(sentinel) int idxLeft = 0, idxRight = 0; for (int i = front; i <= end; i++) { if (LeftSub[idxLeft] <= RightSub[idxRight] ) { Array[i] = LeftSub[idxLeft]; idxLeft++; } else{ Array[i] = RightSub[idxRight]; idxRight++; } } } void MergeSort(std::vector<int> &array, int front, int end){ // front與end為矩陣範圍 if (front < end) { // 表示目前的矩陣範圍是有效的 int mid = (front+end)/2; // mid即是將矩陣對半分的index MergeSort(array, front, mid); // 繼續divide矩陣的前半段subarray MergeSort(array, mid+1, end); // 繼續divide矩陣的後半段subarray Merge(array, front, mid, end); // 將兩個subarray做比較, 並合併出排序後的矩陣 } } ``` 參考 [Comparison Sort: Merge Sort(合併排序法)](http://alrightchiu.github.io/SecondRound/comparison-sort-merge-sorthe-bing-pai-xu-fa.html) ## Heap sort 最重要的是了解抽走max/min後怎麼把樹重新Heapify,下面連結講的很清楚 尚未建成max-heap前,到建成第一個max-heap的過程也要會(參考講義) ==特別注意==:在同一個subtree裡,leftchild(index(2i))與rightchild(index(2i+1))的「數值」大小順序不重要,只要和root(index(i))比較即可。 - Unstable - Space complexity: $O(1)$ - Time complexity: - Worst: $O(n\log n)$ - Avg: $O(n\log n)$ ```cpp= // Code超複雜 跳過 ^_^ ``` 參考 [Comparison Sort: Heap Sort(堆積排序法)](http://alrightchiu.github.io/SecondRound/comparison-sort-heap-sortdui-ji-pai-xu-fa.html) ## Bucket sort - [mega筆記 ch5.Tree](https://drive.google.com/file/d/1DvDNPXXK8ZkiprnQvvR9xdRqYb2nYQzr/view?usp=share_link)說bucket sort為Radix sort的MSD版 - [Rusk algorithm club](https://rust-algo.club/sorting/bucket_sort/index.html)說bucket sort是先裝入桶子在用insertion sort排序 - ex: 1~100, 101~200...901\~1000 假設共r=10桶 - 數字如果平均分散在這個範圍內,每個桶只會有n/10筆資料 - 每個桶用insertion sort,**這邊需假設資料小到能$O(n/r)$時間完成** - 把資料串回來,需要 - Space complexity: $O(n\times r)$ - Time complexity: - Worst: $O(n^2)$ 當所有人擠同一個桶子 - Avg: $O(n+r)$ - d: max number digit / r: buckets ## Radix sort - 主要有MSD/LSD兩種,差別在從最大or最小的digit開始分類 - 講義p.330有分類過程,務必看過 ==桶子是FIFO== - MSD: unstable, LSD: stable - Space complexity: $O(n\times r)$ - Time complexity: - Worst: $O(d\times(n+r))$ - Avg: $O(d\times(n+r))$ - d: max number digit / r: buckets ```cpp= // 我賭不會考 考了應該也憑感覺寫得出來吧(記得桶子用Queue做!!!) ``` 參考 - [線性排序比較 Radix sort / bucket sort / counting sort](https://iq.opengenus.org/counting-sort-vs-radix-sort-vs-bucket-sort/#:~:text=Radix%20sort%20uses%20counting%20sort,a%20stable%20linear%20sorting%20algorithm.) ![](https://hackmd.io/_uploads/S1a_SATNh.png) # Hashing - ### 名詞解釋 - bucket - 分成幾個單位(ex. mod 5就是5個bucket) - slot - 每單位可放幾個record - load density (factor) - n=放入hash的變數各數 - sb=hash table的容量大小 - $\displaystyle \alpha=\frac{n}{sb}$,可以視為平均一個bucket中有幾個人 - collision - 兩個不同字進到同個桶中 - overflow - collision且桶子滿了(no more slots) - perfect hashing - 保證不會有collision發生的hashing function - ### overflow handing - Linear probing - 一個bucket滿了,去下一個bucket放 - Quadratic probing - 如果經過h(x)算出的位置滿了,重算公式如下 - $h(x)\pm i^2$,如果還是滿的,i++ - double hashing - 如果經過h(x)算出的位置滿了,重算公式如下 - $h(x)+i*f(i)$,如果還是滿的,把$i+1$再算一次 - ex. f(i)=(7-x%7) - h(41)+1\*f(1)=h(41)+1*(7-41%7) --->滿的話繼續往下算 - h(41)+2\*f(2)=h(41)+2*(7-41%7) - 以此類推 # 高等樹 [Mega大筆記](https://drive.google.com/drive/folders/1t9mKiqrLc_d9CaVLNtK8Jj8FKcAA3t-C) ## Double-Ended priority queue - Time complexity - Insertion: $O(\lg n)$ - Delete min/max: $O(\lg n)$ - find min/max: $O(\lg n)$ - 皆為Complete (binary) tree - 以下三種都是這種queue - Min-max heap - Deap (Double-Ended-Heap) - Symmetric min-max heap (SMMH) ## Min-Max heap - 一種Double-Ended priority queue - 定義 - Complete Binary Tree - Tree level被分為min level和max level - 若某節點位於min(max) level,則以該點為根的子樹中,他的權重為最小(大)值。 - 第一層(root)必須為min level - [完整介紹 & Insert & Delete](https://medium.com/%E7%8B%97%E5%A5%B4%E5%B7%A5%E7%A8%8B%E5%B8%AB/%E5%9C%96%E8%A7%A3-double-ended-priority-queue-%E9%80%B2%E9%9A%8E%E6%A8%B9-1ae18d2ca402) - 看圖弄懂流程就好,文章廢話太多了 - delete 有分delete min和delete max,略有不同 - [Mega大筆記](https://drive.google.com/drive/folders/1t9mKiqrLc_d9CaVLNtK8Jj8FKcAA3t-C)中,insert的圖示有誤,正確請參考文章 ## Deap (Double-Ended-Heap) - 定義 - 一棵Complete Binary Tree - root不儲存任何資料 - root的左子樹是min-heap ; 右子樹則為max-heap - 在root左子上的任一點 i,令 j 為他在右子樹中對應的節點,i 點的權重必須小於 j 點的權重。(p.s 若無對應點則取其父點) - [完整介紹 & Insert & Delete (Deap在比較下面,文章中很多廢話自行跳過)](https://medium.com/%E7%8B%97%E5%A5%B4%E5%B7%A5%E7%A8%8B%E5%B8%AB/%E5%9C%96%E8%A7%A3-double-ended-priority-queue-%E9%80%B2%E9%9A%8E%E6%A8%B9-1ae18d2ca402) - insert的"對應點"概念,看書很容易理解 - 其他說明都看這篇文章 ## SMMH (Symmetric min-max heap) - 定義 - 是一個Complete Binary Tree,Root不存Data,滿足: 1. 左兄弟 ≤ 右兄弟 (近兄弟) 2. 節點x的祖父的左子點必須 ≤ x 3. 節點x的祖父的右子點必須 ≥ x 對於節點i來說,i的左子點是i的子樹中的最小值(不含i)。 對於節點i來說,i的右子點是i的子樹中的最大值(不含i)。 - [刪除插入文字敘述](https://garychang.gitbook.io/data-structure/lecture2-tree-and-binary-tree/lecture-2.8-advanced-trees/2.8.3-symmetric-min-max-heap) - [刪除](https://publish.get.com.tw/BookPre_pdf/51MM045102-2.pdf) <!-- - [Insert & delete自錄影片](https://www.youtube.com/watch?v=f_wTGAPEqAo) --> ## Extended Binary Tree - **External Node = Failure Node, 數量為internal node+1** - E: External path length - I: Internal path length - N: Internal Node - $E=I+2N$ - [完整介紹](https://hackmd.io/@vRN1CwEsTLyHOsG4mC0d4Q/SJJ6ofDn4) ## Minimal Weighted External path length - 三種求法 - 最常見: Huffman algo $O(n \lg n)$ - 暴力 - DP - [完整介紹](https://hackmd.io/@vRN1CwEsTLyHOsG4mC0d4Q/SJJ6ofDn4) ## Optimal Binary search tree (OBST) 略,見algo筆記 ## AVL tree - 高度平衡樹,$|h_L - h_R| \leq 1$ - AVL定理 - [證明在連結最下面](https://garychang.gitbook.io/data-structure/lecture2-tree-and-binary-tree/lecture-2.8-advanced-trees/2.8.5-avl-tree) - Let 形成高度h的AVL Tree所需最少的節點數為$a_h$ - $a_h = a_{h-1}+a_{h-2}+1$ - $a_h = F_{h+2}-1$,其中$F$為費式數列,這裡令h=0為root height - insert & 完整介紹: 見陳宜欣Slides - [delete](https://www.youtube.com/watch?v=g4y2h70D6Nk) ## B tree - B tree is a **balanced** m-way search tree - 令$t=\lceil\frac{m}{2}\rceil$ - 2 $\leq$ deg(root) $\leq$ m - $\displaystyle t \leq$ deg(node) $\leq m$ - 1 $\leq$ root's key $\leq$ 2t-1 - t $\leq$ node's key $\leq$ 2t-1 - 一個m階的B樹具有如下幾個特徵: 1. 根結點至少有兩個子女。 2. 每個中間節點都包含k-1個元素和k個孩子,其中 m/2 <= k <= m 3. 每一個葉子節點都包含k-1個元素,其中 m/2 <= k <= m 4. 所有的葉子結點都位於同一層。 5. 每個節點中的元素從小到大排列,節點當中k-1個元素正好是k個孩子包含的元素的值域分劃 - Insert & delete: 陳宜欣Slides session 10 <!-- - [5-way B tree插入與刪除 自錄影片](https://youtu.be/AM3XRJ17Bos) --> ## 2-3 tree - B tree of order 3 = 3 way B tree - 內部結點degree為2 or 3 - degree=child數目,一個key的node有兩個child,兩個key的node有三個child - 所有外部結點位於同階層 - 令2-3 tree height = h,internal node = n - $\log_3 (n-1) \leq h \leq \log_2 (n-1)$ - [Insertion](https://www.youtube.com/watch?v=bhKixY-cZHE) - Delete: 看課本(也有[影片](https://www.youtube.com/watch?v=b0naM_7ofYo),但課本講得比較好) ## 2-3-4 tree - B tree of order 4 = 4 way B tree - 有時簡稱2-4 tree - 內部結點degree為2, 3 or 4 - insert還是會從最上面開始,比較大小決定往左or右放 - [Insert & Delete](https://www.youtube.com/watch?v=0tg6sj3SsN4) - [TOP-Down & Bottom up 解法 (包含insert, delete)](http://u.camdemy.com/media/510) - 刪除非常混亂,別的[影片](https://www.youtube.com/watch?v=94e-uBYK5nk)這樣講但我沒懂 ## B+ tree - 很類似B tree,差在B+ tree leaf層才有完整資料,上面都是index,為的是降低IO次數 - 不是每次insert都需在non-leaf node留下自己的index,只有split後,才需要留 - split可以想成依照B tree規則先把資料弄上去,再把資料往下放到右子樹的最小值 以下為交大104資演: ![](https://hackmd.io/_uploads/rk_FBCpEh.png) ans: ![](https://hackmd.io/_uploads/S1CFHAa43.png) 參考[mega ch9 advance tree](https://drive.google.com/file/d/11jcHDxHtX9mexSxrrG-cDBV3rQt2KsX4/view?usp=share_link)筆記 其他參考: [hackmd](https://hackmd.io/@w8qbx0fdRK2ETRnEzcLK2A/SyjKs-mxg?type=view) [B+ tree visualization](https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html) ## red-black tree ![](https://hackmd.io/_uploads/BJV5SR6Eh.png) - 五條規則 - 樹上的每個節點 (node) 只能是紅色或黑色 - 根節點 (root) 一定要是黑色 - 葉節點 (leaf) 一定要是黑色的空值 (NULL) - 紅色節點的兩個子節點 (child) 一定要是黑色 (亦即不能有兩個紅色節點相連,注意:黑色節點的子節點顏色沒有限制) - 從任何節點出發,其下至葉節點所有路徑的黑色節點數目要相同 - [2-3-4 tree to red-black tree](https://azrael.digipen.edu/~mmead/www/Courses/CS280/Trees-Mapping2-3-4IntoRB.html) - [insert](http://alrightchiu.github.io/SecondRound/red-black-tree-insertxin-zeng-zi-liao-yu-fixupxiu-zheng.html) - [delete](http://alrightchiu.github.io/SecondRound/red-black-tree-deleteshan-chu-zi-liao-yu-fixupxiu-zheng.html) - [看印度人講比較快](https://tigercosmos.xyz/post/2019/11/algorithm/red-black-tree/) - 其他資源 - [Red-Black Tree / 紅黑樹 (插入刪除都講得不錯)](https://medium.com/@imprld01/red-black-tree-%E7%B4%85%E9%BB%91%E6%A8%B9-8d793e692d70) - [Red-Black Trees | Deletion](https://www.codesdope.com/course/data-structures-red-black-trees-deletion/) - [Red-Black tree visualization](https://www.cs.usfca.edu/~galles/visualization/RedBlack.html) ## Union set 以下code使用union by rank with path compression ```python= def Make_set(x): x.parent=x x.rank=0 def Find_set(x): if x==x.parent: return x return find_set(x.parent) def Union(x,y): Link(Find_set(x), Find_set(y)) def Link(x,y): if x.rank > y.rank: y.parent=x else: x.parent=y if x.rank == y.rank: y.rank++ ``` - [說明](https://haogroot.com/2021/01/29/union_find-leetcode/) - 複雜度: - Union: $O(1)$ - Find (with union by rank): $O(\alpha (n)) \approx O(1)$ - 另外有union by height , union by size,兩者導致union & find會有$O(\lg n)$ - [ref](http://web.eecs.utk.edu/~jplank/plank/classes/cs302/Notes/Disjoint/#:~:text=Union%20by%20height%3A%20The%20height,node%20whose%20height%20is%20bigger.), [ref2比較詳細](https://www.cs.princeton.edu/courses/archive/spring13/cos423/lectures/UnionFind.pdf), [ref3](https://hackmd.io/@CLKO/rkRVS_o-4?type=view), [ref4](https://yuihuang.com/union-find-algorithm/) - 參考台大102資演題目,當作練習 ## leftist tree 左傾樹 [說明](https://tmt514.gitbooks.io/2016-09/content/tree-ds/leftist-tree.html) - 建議自己畫左傾樹插入1~10,用下面工具比對步驟是否正確,才算完全懂 [visualization](https://www.cs.usfca.edu/~galles/visualization/LeftistHeap.html) ## Binomial queue [影片講得不錯](https://www.youtube.com/watch?v=9G-5jUqQAVc) [圖解](https://gtl.csa.iisc.ac.in/dsa/node141.html) ## Binomial heap, Fibonacci heap [別人的筆記](https://hackmd.io/@Zero871015/DSNote-19) - ![](https://hackmd.io/_uploads/HyT9rCTV3.png) - [圖片來源:高等樹筆記](https://drive.google.com/drive/folders/1t9mKiqrLc_d9CaVLNtK8Jj8FKcAA3t-C) # 補充 - [In-place algorithm (重要)](https://zh.m.wikipedia.org/zh-tw/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95) - Build heap只需要$O(n)$就能完成,而非 $O(n\lg n)$ !!! - ![](https://hackmd.io/_uploads/SJIirCp4n.png) - 複雜度O(n)證明: 最後一個父點所在的layer最多有n/4 nodes,他們最多會往下移動1;再上一層最多有n/8 nodes,他們最多往下移動2;... Top node最多往下移動h ([ref](https://stackoverflow.com/questions/9755721/how-can-building-a-heap-be-on-time-complexity)) - ![](https://hackmd.io/_uploads/SylhB0aVh.png) - merge two heap: $O(n)$ - insert, delete都是$O(\lg n)$ - merge two leftist tree: $O(\lg n)$ - ![](https://hackmd.io/_uploads/SJGaHCpN3.png) - Binary search tree如果不平衡,每次插入/查詢可達$O(n)$ - [Fibonacci search](https://www.youtube.com/watch?v=q_AVjuzBxoc), [ref2](https://hackmd.io/@Aquamay/H1nxBOLcO/https%3A%2F%2Fhackmd.io%2F%40Aquamay%2FSynpeGbiu) (還沒看,但感覺很厲害) - ![](https://hackmd.io/_uploads/Sy4RBR642.png) - 以108清大計科為例: 對1,2,3...16的sequence分別搜尋2, 10, 15所需次數 ``` before search, construct Fn and searched sequence A[] Fibonacci k : 0 1 2 3 4 5 6 7 8 Fk: 0 1 1 2 3 5 8 13 21 A[] i : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 A[i]: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 n = last index of A[] = 15 k=8 (the kth Fibonacci number >= A[n]) offset = -1 search 2: i = min(-1+F(8-2), 15) = min(-1+8, 15) = 7 2<A[7] --> k = 8-2 = 6 i = min(-1+F(6-2), 15) = min(-1+3, 15) = 2 2<A[2] --> k = 6-2 = 4 i = min(-1+F(4-2), 15) = min(-1+1, 15) = 0 A[0]<2 --> k = 4-1 = 3, offset = i = 0 i = min(0+F(3-2), 15) = min(0+1, 15) = 1 A[1]=2 , Find! search 10: i = min(-1+8, 15) = 7 A[7]<10 --> k = 8-1 = 7, offset = 7 i = min(7+5, 15) = 12 10<A[12] --> k =7-2 = 5 i = min(7+2,15) = 9 A[9]=10, Find! search 15: i = min(-1+8, 15) = 7 A[7]<15 --> k = 8-1 = 7, offset = 7 i = min(7+5, 15) = 12 A[12]<15 --> k = 7-1=6, offset = 12 i = min(12+3, 15) = 15 15<A[15] --> k = 6-2 =4 i = min(12+1, 15) = 13 A[13]<15 --> k = 4-1 = 3, offset = 13 i = min(13+1, 15) = 14 A[14] = 15, Find! ```