求二叉树某结点在先序、中序、后序遍历中的访问次序

求二叉树某结点在先序、中序、后序遍历中的访问次序

 

实验内容及要求:

设二叉树采用二叉链表存储结构,结点数据域为字符类型。编写程序,用先序递归遍历法建立二叉树的二叉链表存储结构(输入先序遍历序列时,用字符'*'表示NULL指针)。然后输入一个字符,输出该字符在先、中、后序遍历中的访问次序(访问次序从1开始)以及先、中、后序遍历结果。若输入的字符不在二叉树中,输出相应提示信息。要求程序可以反复输入字符并输出访问次序及遍历结果,当输入的单个字符为'#'时,结束整个应用程序。

注意:输入单个字符时需对其后的换行符进行处理。

实验目的:掌握二叉树的基本算法、提前中止递归的方法,递归函数的形参与返回值设置。

 

#include<iostream>
#include<fstream>
using namespace std;


int countnode = 0;
typedef struct Tree
{
	char e;
	Tree* lchild;
	Tree* rchild;
}T;

T* CreatTree(T* bt, char* temp)//先序建立二叉树
{
	static int i = 0;
	char c;
	//cout << "请输入节点字符" << endl;
	//if ((c = _getche()) == '#')
	if ((c = temp[i++]) == '*')//括号很重要,因为==的优先级大于赋值运算符
		return 0;
	else
	{
		bt = new T;
		countnode++;
		bt->e = c;
		bt->lchild = CreatTree(bt->lchild, temp);
		bt->rchild = CreatTree(bt->rchild, temp);
		return bt;
	}
}
void Preorder(T* bt)
{
	if (!bt)return;
	else
	{
		cout << bt->e << " ";
		Preorder(bt->lchild);
		Preorder(bt->rchild);
	}
}//前序遍历

void PreorderI(T* bt,char e,int &i)//i既用来计数,又用作返回判断的标志变量
{//先序遍历二叉树且计数
	if (!bt||i>0)return;
	else
	{
		if (bt->e == e)
		{
			i--;
			i = -i;
		}
		else
		{
			if (!bt || i > 0)return;
			cout << bt->e << " ";
			i--;
		}
			PreorderI(bt->lchild, e, i);
			PreorderI(bt->rchild, e, i);
	}
}
void Midorder(T* bt)
{
	if (!bt)return;
	Midorder(bt->lchild);
	cout << bt->e << " ";
	Midorder(bt->rchild);
}//中序遍历

void MidorderI(T* bt, char e, int& i)//中序遍历二叉树且计数
{
	if (!bt || i > 0)return;
	MidorderI(bt->lchild, e, i);
	if (bt->e == e)
	{
		i--;
		i = -i;
		return;
	}
	else
	{
		if (!bt || i > 0)return;
		i--;
	}
	MidorderI(bt->rchild, e, i);
}
void Lasorder(T* bt)
{
	if (!bt)return;
	Lasorder(bt->lchild);
	Lasorder(bt->rchild);
	cout << bt->e << " ";
}//后序遍历

void lasorderI(T* bt, char e, int& i)//后序遍历二叉树且计数
{
	if (!bt || i > 0)
		return;
	lasorderI(bt->lchild, e, i);
	lasorderI(bt->rchild, e, i);//子函数执行完,不都会从最上面开始,所以else里面也要有返回判断,保证任何时刻都可以及时退出
	if (bt->e == e)
	{
		i--;
		i = -i;
		return;
	}
	else
	{
		if (!bt || i > 0)
			return;
		i--;
	}
}
int main(void)
{
	char c;
	T* bt = NULL;
	ofstream OutFile("Test.txt");
	OutFile << "ABC**DE*G**F***";//利用文件保存节点,方便测试
	OutFile.close();
	ifstream readFile("Test.txt");
	char temp[100] = { 0 };
	readFile >> temp;
	bt = CreatTree(bt, temp);
	while (1)
	{
		int pre = 0;
		int mid = 0;
		int las = 0;
		cout << "请输入想要查找的节点" << endl;
		cin >> c;
		if (c == '#')
			break;
		Preorder(bt);
		PreorderI(bt, c, pre);
		if (pre < 0)
			cout << "不在树中" << endl;
		else
			cout << "第" << pre << "个遍历" << endl;

		Midorder(bt);
		MidorderI(bt, c, mid);
		if (mid < 0)
			cout << "不在树中" << endl;
		else
			cout << "第" << mid << "个遍历" << endl;

		Lasorder(bt);
		lasorderI(bt, c, las);
		if (las < 0)
			cout << "不在树中" << endl;
		else
			cout << "第" << las << "个遍历" << endl;
	}
	return 0;
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在二叉树的遍历,叶结点是指没有子节点结点。在先序遍历,叶结点是最先遍历的,因为先序遍历先遍历根节点,再遍历左子树,最后遍历右子树。因此,在先序遍历,叶结点的相对次序是最先的。 在中序遍历,叶结点的相对次序在根节点和其他结点之间,因为中序遍历先遍历左子树,再遍历根节点,最后遍历右子树。 在后序遍历,叶结点的相对次序是最后的,因为后序遍历先遍历左子树,再遍历右子树,最后遍历根节点。因此,在后序遍历,叶结点的相对次序是最后的。 ### 回答2: 对于任何一棵二叉树,其叶结点先序中序后序遍历序列的相对次序是相同的。具体来说,假设该二叉树有n个叶结点,对于其任意两个叶结点,它们在先序中序后序遍历序列的相对次序都是相同的。 先序遍历的顺序是根节点,然后左子树和右子树,因此对于任何一个叶结点,它的前面都是其所在子树的根节点和叶结点,而其后面则一定是其同级或者更高级节点的右子树或者向上跳的节点中序遍历的顺序是先左子树,然后根节点和右子树。对于一个叶节点,它前面的是在它左侧的节点,而它后面的是在它右侧的节点后序遍历的顺序是先左子树和右子树,然后根节点。对于一个叶节点,它前面的是在它同侧左边的节点,而它后面的则是在它同侧右边的节点。 因此,可以得出结论是,对于任何一棵二叉树,其叶结点先序中序后序遍历序列的相对次序是相同的。 ### 回答3: 在二叉树先序遍历,第一个遍历的节点一定是根节点,随后按照先左子树后右子树的顺序遍历。当遇到一个叶节点时,遍历就会返回到它父节点的位置,开始遍历父节点的右子树。因此,在先序遍历,叶节点的顺序取决于它们在树出现的先后顺序以及它们所处的深度。 在二叉树中序遍历,根节点被遍历的位置位于间,左边是根节点的左子树,右边是根节点的右子树。因此,对于每个叶节点来说,它们的相对位置取决于它们在树所处的深度。深度越小的节点中序遍历越靠前,深度越大的节点中序遍历越靠后。 在二叉树后序遍历,叶节点是在遍历完左右子树之后才被遍历到的。这意味着,如果一个节点是叶节点,它一定是在它的父节点的左右子树都被遍历完之后才被遍历到的。因此,在后序遍历,叶节点的相对位置与它们在先序中序遍历的顺序不同,而是与它们在树的位置以及它们的深度有关。深度越深的叶节点后序遍历越靠前,深度越浅的叶节点后序遍历越靠后。 综上所述,在不同的遍历方式,叶节点相对位置的顺序都与它们在树的深度和出现位置有关,但是具体的顺序会因为遍历方式不同而产生差异。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值