二叉查找树的算法实现
二叉查找树又叫二叉排序树,属于二叉树的一种特例,是空树或具有如下特点的树:
1.若左子树非空,则左子树上的所有节点的关键字值都小于根节点的关键字。
2.若右子数非空,则右子树上的所有节点的关键字值都大于根节点的关键字。
3 .左右子树又是一个二叉搜索树。
由二叉查找树的定义可知,在一棵非空的二叉查找树中,其结点的关键字是按照左子树、根和右子树有序的,所以对它进行中序遍历得到的结点序列是一个有序序列。
二叉查找树的这种特殊性质使得它在查找元素的时候特别的方便,每一次查找都可以去掉一半的元素,因此查找的时间是O(logN).
以下是二叉查找树的相关操作的算法实现:
1 struct Node{ 2 int data; 3 Node *lchild, *rchild, *parent; 4 }; 5 6 /*在以t为树根的二叉查找树中,递归查找关键字key */ 7 Node* recursion_tree_search(Node *t, int key){ 8 if(t!=NULL || key==t->data) 9 return t; 10 if(key<t->data) 11 return recursion_tree_search(t->lchild, key); 12 else 13 return recursion_tree_search(t->rchild, key); 14 } 15 16 /*在以t为树根的二叉查找树中,非递归查找关键字key */ 17 Node* iterative_tree_search(Node *t, int key){ 18 while(t!=NULL && key!=t->data){ 19 t = (key<t->data)?t->lchild:t->rchild; 20 } 21 return t; 22 } 23 24 /*在以t为树根的二叉查找树中,查找最小元素,返回其指针 */ 25 Node* tree_minimum(Node *t){ 26 while(t->lchild!=NULL){ 27 t = t->lchild; 28 } 29 return t; 30 } 31 32 /*在以t为树根的二叉查找树中,查找最大元素,返回其指针 */ 33 Node* tree_maximum(Node *t){ 34 while(t->rchild!=NULL){ 35 t = t->rchild; 36 } 37 return t; 38 } 39 40 /*查找x结点的直接后继,返回其指针 */ 41 Node* tree_successor(Node *x){ 42 if(x->rchild!=NULL){//如果右子树非空,那么直接后继为右子树的最小元素 43 return tree_minimum(x->rchild); 44 } else{//否则直接后继为x的最低祖先结点,且其直接后继的左孩子也是x的祖先 45 Node *p = x->parent; 46 while(p!=NULL && x==p->rchild){ 47 x = p; 48 p = p->parent; 49 } 50 return p; 51 } 52 } 53 54 /*查找x结点的直接前驱,返回其指针 */ 55 Node* tree_predecessor(Node *x){ 56 if(x->lchild!=NULL){//如果左子树非空,那么直接后继为左子树的最大元素 57 return tree_maximum(x->lchild); 58 } else{//否则直接前驱为x的最低祖先几点,且其直接前驱的右孩子也是x的祖先 59 Node *p = x->parent; 60 while(p!=NULL && x==p->lchild){ 61 x = p; 62 p = p->parent; 63 } 64 return p; 65 } 66 } 67 68 /*在以t为树根的二叉查找树中,插入结点x*/ 69 void tree_insert(Node *t, Node *x){ 70 Node *p = NULL; 71 while(t!=NULL){ 72 p = t; 73 if(x->data < t->data){//插到左子树 74 t = t->lchild; 75 } else{//插到右子树 76 t = t->rchild; 77 } 78 } 79 if(p==NULL){//树为空,直接插入到根结点 80 t = x; 81 } else if(x->data < p->data){//插入到左结点 82 p->lchild = x; 83 x->parent = p; 84 } else{//插入到右结点 85 p->rchild = x; 86 x->parent = p; 87 } 88 } 89 90 /*在以t为树根的二叉查找树中,删除关键字为key的结点。包含三种情况,1.如果x结点 91 没有子女,直接将其删除。2.如果x结点只有一个子女,则删除x,并将x的子女置为x的 92 位置。3.如果x结点有两个子女,则删除其后继结点(它至多有一个子女),接着替换x 93 和x后继结点的关键字*/ 94 Node* tree_delete(Node *t, int key){ 95 Node *x = iterative_tree_search(t, key);//查找关键字key的结点 96 Node *y, *z; 97 if(x->lchild==NULL || x->rchild==NULL){//如果x结点不是同时有左右孩子,将其存到临时变量y 98 y = x; 99 } else{//否则临时变量存x的后继结点; 100 y = tree_successor(x); 101 } 102 //z存y的孩子结点 103 if(y->lchild!=NULL){ 104 z = y->lchild; 105 }else{ 106 z = y->rchild; 107 } 108 109 if(z!=NULL){ 110 z->parent = y->parent; 111 } 112 if(y==NULL){ 113 t = z; 114 } else if(y==y->parent->lchild){ 115 y->parent->lchild = z; 116 } else{ 117 y->parent->rchild = z; 118 } 119 120 if(y != x){ 121 x->data = y->data; 122 } 123 return y; 124 }