【算法導論】學習筆記——第12章 二叉搜索樹

搜索樹數據結構支持多種動態集合操做,包括SEARCH、MINIMUM、MAXIMUM、PREDECESSOR、SUCCESSOR、INSRT和DELETE操做等。基本的搜索樹就是一棵二叉搜索樹。
12.1 什麼是二叉搜索樹
1. 二叉搜索樹的性質:
設x是二叉搜索樹中的一個結點。若是y是x左子樹中的一個結點,那麼y.key<=x.key。若是y是x右子樹中的一個結點,那麼y.key>=x.key。
三種遍歷時間複雜度是O(n),這是顯然的。

12.1-3算法

 1 void Inorder_Tree_Walk_Nonrecursive_1(Node_t *x) {
 2     stack<Node_t *> S;
 3     bool mid = false;
 4 
 5     printf("Using stack to implement Inorder_Tree_Walk:\n");
 6     S.push(x);
 7     while (!S.empty()) {
 8         if (x->l == NULL || mid) {
 9             printf("%d ", x->key);
10             S.pop();
11             if (x->r == NULL) {
12                 if (S.empty())
13                     break;
14                 x = S.top();
15                 mid = true;
16             } else {
17                 x = x->r;
18                 S.push(x);
19                 mid = false;
20             }
21         } else {
22             x = x->l;
23             S.push(x);
24         }
25     }
26     printf("\n");
27 }
28 void Inorder_Tree_Walk_Nonrecursive_2(Node_t *x) {
29     printf("Using nonstack to implement Inorder_Tree_Walk:\n");
30     Node_t *p = x->p, *y = NULL;
31     bool ret = false, retr = false;
32 
33     while (!retr || y!=p) {
34         if (x->l == NULL || ret) {
35             if (!retr)
36                 printf("%d ", x->key);
37             if (x->r == NULL || retr) {
38                 retr = (x == y->r);
39                 x = y;
40                 y = y->p;
41                 ret = true;
42             } else {
43                 y = x;
44                 x = x->r;
45                 ret = false;
46             }
47         } else {
48             y = x;
49             x = x->l;
50         }
51     }
52     printf("\n");
53 }


12.1-5


12.2 查詢二叉搜索樹
除了基本的SEARCH外,還包括MINIMUM、MAXIMUM、SUCCESSOR、PREDESSOR等查詢操做。

12.2-5


12.2-6


12.2-7


12.2-8


12.2-9


12.3 插入和刪除
插入操做比較簡,基本二叉樹的刪除操做須要分類討論。書中使用了一個子函數TRANSPLANT簡化了一些基本操做,使得DELETE過程變得更加清晰。
插入和刪除的時間複雜度都是O(h).

12.3-2


12.3-3


12.3-4
不可交換,反例以下圖:


12.3-5
中文的《算法導論(第3版)》這道題徹底翻譯錯了,去看了一下英文的搞懂了題目作的。
如提示所示,就是利用後繼的屬性從新實現插入、刪除、查找函數。
求結點p的父節點的思路是先求得p所在子樹的最大值,該值所在結點的後繼就是p的父節點。 其他
操做均須要利用後繼的性質。以插入爲例。數據結構

 1 void Tree_Insert(Tree_t *t, Node_t *z) {
 2     Node_t *y = NULL;
 3     Node_t *x = t->root;
 4     while (x != NULL) {
 5         y = x;
 6         if (z->key < x->key)
 7             x = x->l;
 8         else
 9             x = x->r;
10     }
11     if (y == NULL) {
12         t->root = z;    // tree t was empty
13         z->succ = NULL;
14     } else if (z->key < y->key) {
15         Node_t *p = ParentOf(y);
16         z.succ = y;
17         p.succ = z;
18     } else {
19         z->succ = y->succ
20         y->succ = z;
21     }
22 }

 12.4 隨機構建二叉搜索樹
算法導論不少章節都會講隨機算法在數據結構上的隨機化。並且都是大段大段的證實,挺犀利。隨機算法我我的打算單獨花時間學習,所以涉及到的題目都在第二遍讀算導的時候再作。
主要證實一棵有n個不一樣關鍵字的隨機構建的二叉搜索樹的指望高度爲O(lgn)。主要隨機搜索樹的不少基本操做的時間複雜度都是O(lgn)。隨機化的效率仍是很高的,其實能夠寫個隨機數據發生器,測試一下。函數

相關文章
相關標籤/搜索