【算法导论】学习笔记——第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)。随机化的效率还是很高的,其实可以写个随机数据发生器,测试一下。