二叉排序树的插入与遍历(例子是九度1201题)

    二叉树和二叉排序树啥啥的在上数据结构这门课时就没搞懂,时隔两年再看时突然莫名顿悟了一些,特写此心得记录一下,如果有什么地方理解出错了,请留言纠正,谢谢。

    二叉排序树是一种特殊的二叉排序树,满足如下条件:对于树上任意一个结点,其上的数值必大于等于其左子树上任意结点的数值,必小于等于其右子树上任意结点的数值。

    二叉树的插入:1、若目前树为空,则插入第一个数,作为根节点。2、目前树不为空,则从根节点开始比较,若小于(等于)根结点,且根节点左孩子为空,则插入第二个数作为根节点的左孩子;若不为空,则与根节点的左孩子比较。若大于(等于)根结点,且根节点右孩子为空,则插入第二个数作为根节点的右孩子;若不为空,则与根节点的右孩子比较。3、每插入一个数都是从根节点开始比较,重复2的步骤直到插入结束。(括号中的等于根据不同题目要求具体看是否要包括等于的情况)

    由于各个数字的插入顺序不同,所得的二叉排序树的形态也很可能不同。但是,所有的二叉排序树的中序遍历都是一个递增的序列,通过建立二叉排序树就能对原无序序列进行排序,并实现动态维护

    二叉树的遍历遍历分为三种,先序遍历、中序遍历、后序遍历。先序遍历是按照根左右的顺序,中序是左根右,后序是左右根,个人感觉看代码更容易理解遍历的实现过程,语文不好难以描述┑( ̄Д  ̄)┍

    借助例子来看看吧(借用九度1201题二叉排序树)

    题目描述:

         输入一系列整数,建立二叉排序数,并进行前序,中序,后序遍历。

    输入:

         输入第一行包括一个整数n(1<=n<=100)。
         接下来的一行包括n个整数。

    输出:

         可能有多组测试数据,对于每组数据,将题目所给数据建立一个二叉排序树,并对二叉排序树进行前序、中序和后序遍历。
         每种遍历结果输出一行。每行最后一个数据之后有一个空格。

    样例输入:
5
1 6 5 9 8
    样例输出:
1 6 5 9 8 
1 5 6 8 9 
5 8 9 6 1 
提示:

输入中可能有重复元素,但是输出的二叉树遍历序列中重复元素不用输出。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct node   //定义节点的结构体
{
	node *lchild;   //左孩子
	node *rchild;   //右孩子
	int c;    //节点的数值
}tree[201]; 
/*数据采用全局变量节省了函数间互相传参的麻烦,不过也要慎用*/
int loc;   //loc表示申请了空间的节点的个数
node *t;    //构建的二叉排序树
node *ret;   //当前申请空间的节点
node* create()     //结点的空间申请函数,返回该节点对应的结构体指针
{
	tree[loc].lchild = tree[loc].rchild = NULL;    //初始化左右子树为空
	return &tree[loc++];     //返回指针后,loc再++
}
void build(node *k,int s)
{      
	if (s < k->c)   //从根节点开始比较
	{
		if (k->lchild == NULL)  //如果比较的节点的左孩子为空
		{
			ret = create();  //则创建新节点,并作为该节点的左孩子
			ret->c = s;
			k->lchild = ret;
		}
		else               //如果左孩子不为空,则递归访问节点的左孩子
		{
			build(k->lchild,s);
		}
	}
	else if (s > k->c)   //大于的情况与小于相似,就不赘述了
	{
		if (k->rchild == NULL)
		{
			ret = create();
			ret->c = s;
			k->rchild = ret;
		}
		else
		{
			build(k->rchild,s);
		}
	}
}
void inorder(node *t)   //先序遍历
{
	printf("%d ", t->c);   //遍历该结点,输出其字符信息
	if (t->lchild != NULL)   //若左子树不为空
	{
		inorder(t->lchild);    //递归遍历其左子树
	}
	if (t->rchild != NULL)   //若右子树不为空
	{
		inorder(t->rchild);    //递归遍历其右子树
	}
}
void midorder(node *t)  //中序遍历
{
	if (t->lchild != NULL)   //若左子树不为空
	{
		midorder(t->lchild);    //递归遍历其左子树
	}
	printf("%d ", t->c);    //遍历该结点,输出其字符信息
	if (t->rchild != NULL)   //若右子树不为空
	{
		midorder(t->rchild);    //递归遍历其右子树
	}
}
void postorder(node *t)    //后序遍历
{
	if (t->lchild != NULL)   //若左子树不为空
	{
		postorder(t->lchild);    //递归遍历其左子树
	}
	if (t->rchild != NULL)   //若右子树不为空
	{
		postorder(t->rchild);    //递归遍历其右子树
	}
	printf("%d ", t->c);    //遍历该结点,输出其字符信息
}
int main()
{
	int i,n,arr[201];   //n为节点个数,arr为所有节点数值的数值,也可采用动态数组
	while (scanf("%d",&n)!=EOF)  //因为输入可能包含多组数据,重复读入n,直到n为文件结束符
	{
		for (i = 0; i < n; i++)
			scanf("%d", &arr[i]);  //读入节点的数值
		loc = 0;
		t = create();  //创建根节点
		t->c = arr[0];
		for (i = 1; i < n; i++)   //从第二个数值开始插入
			build(t,arr[i]);   
		inorder(t);  //先序遍历
		printf("\n"); 
		midorder(t);  //中序遍历
		printf("\n");
		postorder(t);  //后序遍历
		printf("\n");
	}
	return 0;
}

由于数字插入顺序不同会导致二叉排序树的不同,但这种情况下的中序遍历是相同的,所以需要中序遍历+先序遍历 或 中序遍历+后序遍历才能确定唯一的二叉树。


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值