二叉搜尋樹
二叉搜尋樹是能夠高效進行如下操作的資料結構:
#插入一個數值
#查詢是否包含某個數值
#刪除某個數值
二叉搜尋樹能夠高效地管理數的集合。
其上的所有節點,都滿足左子樹上的所有節點都比自己的小,而右子樹上的所有節點都比自己大的這一條件
下面是二叉搜尋樹的一種實現方法
struct node { int val; node *lch, *rch; }; //插入數值x node *insert(node *p, int x) {if (p==NULL) { node *q = new node; q->val = x; q->lch = q->rch = NULL; return q; } else { if(x<p->val) p->lch = insert(p->lch, x);/*遞迴插入左子樹*/ else p->rch = insert(p->rch, x); /*遞迴插入右子樹*/ return p; } } //查詢數值x bool find(node *p, int x) { while (p) { if (x>p->val) p = p->rch; else if (x<p->val) p = p->lch; else return true; } return false; } //刪除數值x node *remove(node *p, int x) { if(p==NULL) return NULL; else if (x < p->val) p->lch = remove(p->lch, x);/* 從左子樹遞迴刪除 */ else if (x > p->val) p->rch = remove(p->rch, x);/* 從右子樹遞迴刪除 */ else if (p->lch==NULL) { node *q = p->rch; delete p; return q; } else if (p->lch->rch==NULL) { node *q = p->lch; q->rch = p->rch; delete p; return q; } else { node *q; for (q = p->lch; q->rch->rch!=NULL; q = q->rch); node *r = q->rch; q->rch = r->lch; r->lch = p->lch; r->lch = p->rch; delete p; return r; } return p; }
附:二叉搜尋樹的刪除可能稍微麻煩一點,需分以下幾種情況進行處理:
#需要刪除的節點沒有左兒子,那麼就把右兒子提上去
#需要刪除的節點的左兒子沒有右兒子,那麼就把左兒子提上去
#以上兩種情況都不滿足的話,就把左兒子的子孫中最大的節點提到需要刪除的節點上
(之所以會有這幾種情況,按我的想法來說,開始的時候可以將這棵樹看作是滿二叉樹,那麼要進行刪除操作的話只需就把左兒子的子孫中最大的節點提到需要刪除的節點上即可。 但是 q->rch->rch!=NULL 相關操作會導致,如果出現需要刪除的節點的左兒子沒有右兒子的這種情況,訪問就會越界,因此就有了第二種情況。最後整體再優化一下,不是所有的二 叉樹都要進行復雜的操作,對有些情況可以進行簡單處理,於是就有了第一種情況)