--- tags: algorithm --- # 二元搜尋樹 ## 原理 讓每一個節的的右邊的值都是大於他的,左邊則是小於 ```graphviz digraph main { k k -> "<k" k -> ">=k" } ``` 通常用指標實作,因為不知道層數,如果用陣列開的話會很慘 ## 節點 如上文所述,可知一個節點必須要有兩個指標,一個指向大於他的節點,另一個指向小於他的節點 ```cpp = struct node { node *l, *r; int val; node(int k) : val(k){l = r = nullptr;} } ``` ## 操作 ### 插入 `void insert(int val, node *& cur)` 加參照的原因是因為會有新的節點加入。 ``` cpp = void insert(node *& cur, int k) { if(!cur) {cur = new ndoe(k); return;} if(k < cur -> val) { insert(cur -> l, k); } else { insert(cur -> r, k); } } ``` :::spoiler 實作注意 要記得return ::: --- ### 查詢 查詢一個值是否存在於這個二元樹裡面 `bool qry(node *cur, int k)` ```cpp = bool qry(node *cur, int k) { if(!cur) return false; if(k < cur -> val) { qry(cur -> l, k); } else if(k > cur -> val) { qry(cur -> r, k); } else return true; } ``` :::spoiler 實作注意 一樣要記得return ::: --- ### 時間複雜度 ***插入*** : 平均複雜度$O(\log N)$, 最壞複雜度$O(N)$ ***查詢*** : 平均複雜度$O(\log N)$, 最壞複雜度$O(N)$ :::spoiler complete code ```cpp = struct BST { struct node { node *l, *r; int val; node (int k) : val(k) {l = r = nullptr;} }*root = nullptr; //插入 void insert(node *& cur, int k) { if(!cur) {cur = new node(k); return;} if(k >= cur -> val) { insert(cur -> r, k); } else insert(cur -> l, k); } void insert(int k) {insert(root, k);} //查詢 bool qry(node *cur, int k) { if(!cur) return false; if(k < cur -> val) { qry(cur -> l, k); } else if(k > cur -> val) { qry(cur -> r, k); } else return true; } bool qry(int k) {return qry(root, k);} //印出 (升序) void out(node *cur) { if(!cur) return; out(cur -> l); cout << cur -> val << ' '; out(cur -> r); } void out() {out(root); cout << endl;} }; ```