# C++用一个函数解决二叉树节点查找、求高度、求父节点

C++用一个函数解决二叉树节点查找、求高度、求父节点

写代码的原因和思路:

原因:网上好多关于二叉树的节点查找、求高度、求父节点都是分开的,在求父节点的时候,甚至用到了,这样很麻烦。这里推荐一种合体式的解决方法。
思路:首先,以下代码都是在已经成功创建一棵二叉树的情况下进行的。
引导:首先是节点查找。只需要在使用先序、中序、后序遍历的任何一种方法的时候,将访问函数visit()设置为比对即可:
这里以先序遍历为例子:

查找节点

void BiTree::preTraverse(Binode*&root)//先序遍历
{
   if (root != NULL)
   {
   	visit();
   	preTraverse(root->lChild);
   	preTraverse(root->rChild);
   }
}
void visit()
{
		if (root->data == x)//找到了所需要的节点
		{
			needed = root;//把所需要的节点返回回去,注意needed是后来引入的,前面没写
			return;//结束
		}
}

注意:以上代码是不能直接运行的,只是帮助分析
这样节点查找的功能就完成了。

求高度

前期我尝试过引入一个int型的变量,然后每次遍历的时候加1,但是很快发现这样会把高度多算。
尝试代码如下:

void visit()//假设在原来的基础上 引用& 了一个int型的height=1
{
		if (root->data == x)//找到了所需要的节点
		{
			needed = root;//把所需要的节点返回回去,注意needed是后来引入的,前面没写
			return;//结束
		}
		height++;//高度增加
}

这样写的错误在于:由F到G的时候,高度还在增加,但是此时不应该变化。(如图)
在这里插入图片描述
解决方法是不要使用“引用&”而在每次遍历的时候,在函数头上增加高度。如图:

void BiTree::findnode(char x, Binode * root,Binode *&needed,int height,int &height_need)
//height是一个中间量,而height_need是你需要的最终结果
{
	if (root != NULL)
	{
		if (root->data == x)
		{
			needed = root;
			height_need=height;//如果找到了节点,就把 中间量 赋值给 所需量
			return;
		}

		findnode(x, root->lChild, needed, height + 1,height_need);//注意,高度是在头函数增加的!
		findnode(x, root->rChild, needed, height + 1,height_need);
	}
}

以上代码的不同之处在于,中途引入的height只是一个中间变量,而且不会随着一直增加,因为直接使用int型,所以每次遍历实际上是复制了上一次的结果,所以说——对于此图:
在这里插入图片描述
F处的height是上一个D的height+1=3+1=4;而到G的时候,因为F时函数内的height并不影响G时函数内的height,所以G内的height依旧是D的height+1=4.
因此,高度问题也解决了。

求父节点

根据上面同样的道理,我们很容易就想到:在遍历的时候,如果没有找到需要的点,就把该节点保留成父节点。
例如:遍历到AA不是所需要的,下一个将遍历B,此时保存A就是父节点。
在这里插入图片描述
这样的思路同样有一个问题,就是由FG时,会得到G的父节点是F,这显然是错的,应该是F的前一个D
和求高度同样的方法:可以设置一个中间量,而不使用“引用&”,这样就能得到所需的父节点,实现代码如下:

void BiTree::findnode(char x, Binode * root,Binode *&needed,Binode *father,Binode*&father_need)
//father是中间变量,father_need是最终所需要的父节点
{
	if (root != NULL)
	{
		if (root->data == x)
		{
			needed = root;
			father_need = father;
			return;
		}
		else//如果没找到,就记录该节点为父节点
		{
			father = root;
		}
		findnode(x, root->lChild, needed, father, father_need);//左右遍历
		findnode(x, root->rChild, needed, father, father_need);
	}
}

这样就完成了父节点的确定。
将以上代码整合到一起:

完整可行代码:

void BiTree::findnode(char x, Binode * root,Binode *&needed,Binode *father,Binode*&father_need,int height,int &height_need)
{
	if (root != NULL)
	{
		if (root->data == x)
		{
			needed = root;
			height_need=height;
			father_need = father;
			return;
		}
		else
		{
			father = root;
		}
		findnode(x, root->lChild, needed, father, father_need,height + 1,height_need);
		findnode(x, root->rChild, needed, father, father_need,height + 1,height_need);
	}
}

分析:

该函数的缺点是引入了六个参数,参数很多,容易出错。
该函数的优点是仅使用了一个函数就同时求得了待求节点,高度,父节点。

实现:

	cout << "请输入要查找的数据:" << endl;
	cout << "要输入几次数据:" << endl;
	int n; cin >> n;
	cout << "请输入数据:" << endl;
	for (int i = 0; i < n; i++)
	{
		Binode*father = NULL;//重点在于先将父节点置空
		Binode*needed = NULL;//将待查节点置空
		int height = 0;//高度初始化为0
		char x;
		cin >> x;
		a.findnode(x, root, needed, NULL, father,1, height);//使用查找函数
		if (needed != NULL)//判断待查节点是否存在
		{
			cout << "数据" << x << "存在!" << endl;
			cout << "此数据在第" << height << "层!" << endl;
			if (father == NULL)//无父节点的情况
				cout << "无父节点!" << endl;
			else//输出兄弟节点
			{
				if (father->lChild != NULL && father->rChild != NULL)
				{
					if (father->lChild = needed)
						cout << "存在右兄弟:" << father->rChild->data << endl;
					else
						cout << "存在左兄弟:" << father->lChild->data << endl;
				}
				else
					cout << "无兄弟节点!" << endl;
			}
		}
		else//待查祭奠不存在的情况
			cout << "数据" << x << "不存在!" << endl;
	}

截图说明:

在这里插入图片描述

对于此二叉树:
在这里插入图片描述
感谢阅读!

  • 9
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值