---
# System prepended metadata

title: 二元搜尋樹
tags: [algorithm]

---

---
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;}


};
```
