“二叉查找树”学习
查找二叉树的定义:
存储结构和二叉树相同:
需要实现的方法:
代码:
tree.h
#ifndef _TREE_H
#define _TREE_H
typedef int ElemType;
typedef struct treenode
{
ElemType data;
struct treenode * left;
struct treenode * right;
}TREE;
TREE *MakeEmptyTree();
TREE *InsertTreeNode(ElemType e,TREE *t);
TREE *FindTreeNode(ElemType e,TREE *t);
TREE *FindMax(TREE *t);
TREE *FindMin(TREE *t);
TREE *DeleteTreeNode(ElemType e,TREE *t);
void DeleteTree(TREE **t);
#endif
tree.c
#include<stdio.h>
#include<stdlib.h>
#include"tree.h"
TREE *MakeEmptyTree()
{
return NULL;
}
TREE *InsertTreeNode(ElemType e,TREE *t)
{
if(t == NULL)
{
t = (TREE *)malloc(sizeof(TREE));
if(t == NULL) return NULL;
t->data = e;
t->left = t->right = NULL;
}else if(e < t->data)
t->left = InsertTreeNode(e,t->left);
else
t->right = InsertTreeNode(e,t->right);
return t;
}
TREE *FindTreeNode(ElemType e,TREE *t)
{
if(t == NULL) return NULL;
if(t->data == e)
return t;
else if(t->data < e)
return FindTreeNode(e,t->right);
else
return FindTreeNode(e,t->left);
}
TREE *FindMax(TREE *t)
{
if(t == NULL)
return NULL;
if(t->right == NULL)
return t;
return FindMax(t->right);
}
TREE *FindMin(TREE *t)
{
if(t == NULL)return NULL;
if(t->left == NULL)
return t;
return FindMin(t->left);
}
TREE *DeleteTreeNode(ElemType e,TREE *t)
{
TREE *p = NULL;
if(t == NULL)return NULL;
if(t->data > e)//数据比根小
t->left = DeleteTreeNode(e,t->left);//去左子树删
else if(t->data < e)
t->right = DeleteTreeNode(e,t->right);//去右子树删
//这个节点就是要删的
else if(t->left && t->right)//有两个子节点的节点
{
//找出右子树里最小的
p = FindMin(t->right);
t->data = p->data;
t->right = DeleteTreeNode(t->data,t->right);
}else//要删除的节点有一个子节点或就是叶子节点
{
p = t;
if(t->left == NULL)//右数有
t = t->right;
else if(t->right == NULL)
t = t->left;
free(p);
return t;
}
return t;
}
void DeleteTree(TREE **t)
{
if(*t == NULL)
return;
DeleteTree(&((*t)->left));
DeleteTree(&((*t)->right));
free(*t);
*t = NULL;
}
重点解释一下删除一个节点的算法:
包括两种情况,首先这种是要删除单子树节点的情况:
else//要删除的节点有一个子节点或就是叶子节点
{
p = t;
if(t->left == NULL)//右数有
t = t->right;
else if(t->right == NULL)
t = t->left;
free(p);
return t;
}
这里是只有左子树,那么只要把他的左节点挂到根上面去。程序实现就是直接返回这个左节点。
如果要删除的是叶子节点,比如删除上图的3,那么执行第一条语句时:
if(t->left == NULL) t = t->right;
就已经把t赋值为右数,第二条赋值左树,都是NULL所以最终t就是NULL,返回的也就是NULL。
释放p,就是原来的t,就成功删除了叶子节点3.
第二种情况就是要删除的是有双子树的一个节点:
else if(t->left && t->right)//有两个子节点的节点
{
//找出右子树里最小的
p = FindMin(t->right);
t->data = p->data;
t->right = DeleteTreeNode(t->data,t->right);
}
我们可以找出右子树的最小的节点,当然也可以是左子树最大的节点,先把它的数据提上来,将它递归删除掉。
testBSTree.c
#include<stdio.h>
#include"tree.h"
void main()
{
int n;
TREE *tree = MakeEmptyTree(),*p;
while(1)
{
printf("Please enter a num:");
fflush(stdin);
if(scanf("%d",&n) != 1)
break;
if(n == 0)
break;
tree = InsertTreeNode(n,tree);
}
printf("Max of tree is %d,min of tree is %d\n",
FindMax(tree)->data,FindMin(tree)->data);
fflush(stdin);
printf("Please enter search num:");
scanf("%d",&n);
if(FindTreeNode(n,tree))
printf("find %d\n",n);
else
printf("not find\n");
p = DeleteTreeNode(n,tree);
if(p)
printf("delete %d success\n",n);
else
printf("delete fail\n");
DeleteTree(&tree);
if(tree == NULL)
printf("delete success\n");
else
printf("fail\n");
}
运行时:
可以看到最大值输出76,最小值4,找到7,删除了7这个节点,进而删除了整棵树。













浙公网安备 33010602011771号