以下着重说删除,分3种情况:
case 1:要删除的节点t即有左子树又有右子树,如图c的node 5
case 2:要删除的节点即没左子树又没右子树,如图a的node 13
case 3:要删除的节点有单支子树,或左或右,如图b的node 16或node 10,另外也要注册被删除节点是父亲的左还是右子树
点击(此处)折叠或打开
- #include <stdio.h>
- #include <stdlib.h>
- typedef struct BiTree {
- int data;
- struct BiTree* lchild;
- struct BiTree* rchild;
- }BST;
- void visit_node(BST* t)
- {
- if(t != NULL)
- printf("%d\n", t->data);
- }
- /* 遍历整个树,中序遍历 */
- void traverse_tree(BST* t)
- {
- if(t == NULL)
- return;
- traverse_tree(t->lchild);
- visit_node(t);
- traverse_tree(t->rchild);
- }
- #if 0
- /* 插入节点,递归方法 */
- BST* insert_node_recursion(BST** t, int v)
- {
- if(*t == NULL) {
- *t = (BST*)malloc(sizeof(BST));
- (*t)->data = v;
- (*t)->lchild = (*t)->rchild = NULL;
- return *t;
- }
-
- if (v < (*t)->data)
- (*t)->lchild = insert_node_recursion(&((*t)->lchild), v);
- else
- (*t)->rchild = insert_node_recursion(&((*t)->rchild), v);
-
- return *t;
- }
- #else
- /* 插入节点,递归方法 */
- BST* insert_node_recursion(BST* t, int v)
- {
- if(t == NULL) {
- BST* n;
- n = (BST*)malloc(sizeof(BST));
- n->data = v;
- n->lchild = n->rchild = NULL;
- return n;
- }
-
- if (v < t->data)
- t->lchild = insert_node_recursion(t->lchild, v);
- else if(v > t->data)
- t->rchild = insert_node_recursion(t->rchild, v);
- return t;
- }
- #endif
- /* 插入节点,普通方法 */
- BST* insert_node_normal(BST* t, int v)
- {
- BST* pre = NULL;
- BST* new = NULL;
- BST* head = t;
- int l, r;
-
- while(t && t->data != v) {
- pre = t;
- l = r = 0;
- if(v < t->data) {
- l = 1;
- t = t->lchild;
- } else {
- r = 1;
- t = t->rchild;
- }
- }
-
- new = (BST*)malloc(sizeof(BST));
- new->data = v;
- new->lchild = new->rchild = NULL;
-
- if (pre != NULL)
- l ? (pre->lchild = new) : (pre->rchild = new);
-
- if(head == NULL)
- return new;
- else
- return head;
- }
- /* 查找节点 */
- BST* search_node(BST* t, int v)
- {
- int level = 0;
-
- while (t) {
- level++;
- if(v == t->data) {
- printf("found it, deep level is %d\n", level);
- break;
- } else if(v < t->data)
- t = t->lchild;
- else
- t = t->rchild;
- }
-
- if(!t) {
- printf("node %d is not exist.\n", v);
- return NULL;
- } else
- return t;
- }
- /* 删除节点 */
- void delete_node(BST* t, int v)
- {
- BST* pre = NULL;
- BST* find = NULL;
- BST* parent = NULL;
- BST* most_left = NULL;
- int l, r;
-
- while (t) {
- if(v == t->data) { //找到要删除的这个节点了
- find = t;
- if(t->lchild && t->rchild) { //case 1:要删除的节点t即有左子树又有右子树,删除过程总3步
- //找到t的右子树里的最左节点 @1步
- t = t->rchild;
- while (t->lchild) {
- parent = t; //记录最左结点的父亲
- t = t->lchild;
- }
- most_left = t;
-
- //最左节点代替被删除节点t的位置 @2步
- find->data = most_left->data;
-
- //上面有人被删除带走,最左节点升职上去了,所以要重新调整下最左节点的上下关系,并删除其占用的空间 @3步
- if (most_left->rchild)
- parent->lchild = most_left->rchild;
- else
- parent->lchild = NULL;
- free(most_left);
- most_left = NULL;
-
- break;
- }
- else if(!t->lchild && !t->rchild) //case 2:要删除的节点即没左子树又没右子树
- //l为真表示要删除的节点是父亲的左孩子,所以把左子树指针置空,否则置空右子树指针
- l ? (pre->lchild = NULL) : (pre->rchild = NULL);
-
- else if(t->lchild) //case 3:要删除的节点有左子树
- //要删除的结点为t,t的父亲是pre,t有个左儿子是t->lchild
- //t被带走了,所以把t的孩子过继给t的父亲pre,也就是爷爷来带孙子
- //那么爷爷是左胳膊牵着孙子走还是右胳膊呢,那得看t是pre的左孩子还是右孩子
- //l为真表示要删除的节点t是父亲pre的左孩子,所以把t的孩子过继给父亲pre的左子树,否则就过继给右子树
- l ? (pre->lchild = t->lchild) : (pre->rchild = t->lchild);
-
- else if(t->rchild) //case 4:要删除的节点有右子树
- //同case 3一样,都是过继孙子给爷爷的故事,只不过这个是右孩子,case 3是左孩子
- r ? (pre->rchild = t->rchild) : (pre->lchild = t->rchild);
-
- free(find);
- find = NULL;
- break;
- } else if(v < t->data) {
- pre = t; //pre代表当前节点的父亲
- l = 1; //l变量为真表示当前节点是父亲节点的左子树
- r = 0;
- t = t->lchild;
- } else {
- pre = t;
- r = 1; //r变量为真表示当前节点是父亲节点的右子树
- l = 0;
- t = t->rchild;
- }
- }
- }
- /* 创建二叉查找树 */
- void create_bitree(BST** t, int *d, int len)
- {
- int i;
-
- for(i = 0; i < len; i++)
- // *t = insert_node_recursion(*t, d[i]);
- *t = insert_node_normal(*t, d[i]);
- }
- void main(void)
- {
- //T是整个树的根
- BST* T = NULL;
- int n = 0;
- // int d[] = {4, 13, 3, 9, 28, 6};
- int d[] = {4, 13, 3, 9};
-
- while(d[n++] != 0);
- create_bitree(&T, d, n - 1);
- // insert_node_recursion(T, 15);
- insert_node_normal(T, 15);
- traverse_tree(T);
- printf("\n\n");
- // search_node(T, 9);
- delete_node(T, 4);
- traverse_tree(T);
- }