1、二叉查找树:左子树的值小于根结点,右子树的值大于根结点的树
二叉查找树的中序遍历结果是从小到大的排序。
前面已经介绍了二叉查找树的基本操作,下面通过完整的代码来演示一下,会有助于更好的理解。
2、例:将数组{4,2,5,10,6,3,7,8,1,9}插入为二叉查找树,并按照前序、中序、后序遍历,再删除一个结点后中序遍历输出。最后销毁二叉查找树
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode{
int Data;
struct TreeNode* Left;
struct TreeNode* Right;
}Node;//定义结构体
void preorder_tree(Node* tree)//前序遍历
{
if(tree != NULL)
{
printf("%d ", tree->Data);//第一次遇到就输出
preorder_tree(tree->Left);
preorder_tree(tree->Right);
}
}
void midorder_tree(Node* tree)//中序遍历
{
if(tree != NULL)
{
midorder_tree(tree->Left);
printf("%d ", tree->Data);//第二次遇到输出
midorder_tree(tree->Right);
}
}
void posorder_tree(Node* tree)//后序遍历
{
if(tree != NULL)
{
midorder_tree(tree->Left);
midorder_tree(tree->Right);
printf("%d ", tree->Data);//第三次遇到输出
}
}
Node * find(int x,Node* tree)//查找
{
if(tree == NULL)
return NULL;
else if(x < tree->Data)
return find(x,tree->Left);
//如果查找的值比当前节点小,就返回查找的值和左子树
else if(x > tree->Data)
return find(x,tree->Right);
//如果查找的值比当前节点大,就返回查找的值和右子树
else
return tree;//找到了,就返回当前节点
}
Node* findmax(Node* tree)//递归实现 ,查找最大值
{
if(tree == NULL)
return NULL;
else if(tree->Right == NULL)
return tree;
else
return findmax(tree->Right);
}
Node * findmin(Node *tree)//非递归实现 ,查找最小值
{
if(tree == NULL)
return NULL;
else
{
while(tree->Left != NULL)
tree = tree->Left;
}
return tree;
}
Node* insert(int x,Node* tree)//插入结点
{
if(tree == NULL)//若原树为空,生成并返回一个二叉树
{
tree = (Node*)malloc(sizeof(Node));
if(tree == NULL)//判断是否申请成功
{
printf("no pace!\n");
exit(0);
}
tree->Data = x;
tree->Left = tree->Right = NULL;
}
//开始找插入的位置
else if(tree->Data > x)//递归插入左子树
tree->Left = insert(x,tree->Left);
else if(tree->Data < x)//递归插入右子树
tree->Right = insert(x,tree->Right);
/*else x存在,不做任何操作,返回原树*/
return tree;
}
Node* Delet(int x,Node* tree)//删除结点
{
if(tree == NULL)
{
printf("未找到删除的结点!\n");
}
else if(x > tree->Data)
tree->Right = Delet(x,tree->Right);
else if(x < tree->Data)
tree->Left = Delet(x,tree->Left);
else
{
Node* temp;
if(tree->Left &&tree->Right)//有左子树和右子树的情况
{
temp = findmin(tree->Right);
//在右子树中找最小的元素,然后代替删除的结点
tree->Data = temp->Data;
tree->Right = Delet(tree->Data,tree->Right);
//在右子树中删除最小元,
//因为最小元一定是右子树中最左边的,只有一个孩子或者没有孩子,
//简化了删除操作
}
else//被删除的有一个子结点或没有子结点的
{
temp = tree;
if(tree->Left == NULL)//有右儿子或者无儿子
tree = tree->Right;
else if(tree->Right == NULL)//有左儿子或者无儿子
tree = tree->Left;
free(temp);
}
}
return tree;
}
void destroy_tree(Node* tree)//销毁二叉查找树
{
if (tree==NULL)
return ;
if (tree->Left != NULL)
destroy_tree(tree->Left);
if (tree->Right != NULL)
destroy_tree(tree->Right);
free(tree);
}
int main()
{
Node * tree = NULL;
int a[10] = {4,2,5,10,6,3,7,8,1,9}; for(int i = 0;i<10;i++) { tree = insert(a[i],tree);//插入成为二叉搜索树 } printf("前序遍历结果:"); preorder_tree(tree); printf("\n中序遍历结果:"); midorder_tree(tree); printf("\n后序遍历结果:"); posorder_tree(tree); printf("\n最小值:"); Node *temp = findmin(tree); printf("%d\n",temp->Data); printf("最大值:"); temp = findmax(tree); printf("%d\n",temp->Data); printf("请输入要删除的结点:"); int num; scanf("%d",&num); tree = Delet(num,tree); printf("\n删除结点后的中序遍历:"); midorder_tree(tree); destroy_tree(tree);//销毁树 return 0; }
运行结果:
通过这个简明的例子,相信对二叉查找树有了更深的理解,将分块的代码组合成完整的代码,可以检查代码存在的一些问题,也有助于知识点的巩固。