包含指向父结点指针的特殊二叉树的遍历,要求空间复杂度 O(1)

对于二叉树的遍历,最简单的有递归遍历,另外有比较常见的用栈来实现非递归遍历。今天讲的题目是一个特殊的二叉树,且不允许改变二叉树,实现 O(1) 空间复杂度的前序遍历,二叉树如下:


这个二叉树比较特殊,多了一些蓝色的指针,指向父结点。所以我们可以不用栈来实现回溯了,可以做到空间复杂度为 O(1)。

这是我碰到的一个面试题,当时面试官给我的提示是:从哪里来到哪里去。 我琢磨了一下,想到了其实要知道一个结点是否该回溯了,不需要知道左子树右子树所有结点是否已遍历完,只需要知道左子结点和右子结点是否已遍历完就可以了。

既然空间复杂度为 O(1),那就只能额外申请固定个数的变量(和结点个数无关),在这里只需要申请一个 Node* pre 变量就可以了,思路:

(1) 当 pre 结点是父结点,或空(根结点),代表该继续往下遍历,此时应打印当前结点,并将 pre 设置为当前结点,当前结点设置为左子结点(存在的话),否则是右子结点,若没有孩子,则应该回溯。

(2) 当 pre 结点是左子结点,此时应该继续访问右子树,应该讲 pre 结点设置为当前结点,当前结点设置为右孩子(存在的话)

(3) 当 pre 结点是右孩子,应该回溯,将 pre 设置为当前结点,当前结点设置为父结点。

当时有了这个思路之后,就自己在脑子里过了一遍二叉树的遍历,遍历的结束点为根结点,条件为左右子树都遍历完,且无父结点。

我的代码如下,感觉 while 循环的结束条件不太简洁,但一时又没想到其他的写法。希望各位读者有好的方法的话麻烦留言告知,互相学习!

void PrintTree(Node* pRoot)
{
	if (!pRoot)
	{
		return;
	}
	Node* p = pRoot;
	Node* pre = nullptr;
	while (!((p->pLeft && !p->pRight && pre == p->pLeft && p->pParent == nullptr) || (p->pRight && pre == p->pRight && p->pParent == nullptr)))
	{
		if (pre == p->pParent || pre == nullptr)
		{
			cout << p->value << std::endl;
			if (p->pLeft)
			{
				pre = p;
				p = p->pLeft;
			}
			else if (p->pRight)
			{
				pre = p;
				p = p->pRight;
			}
			else
			{
				pre = p;
				p = p->pParent;
			}
		}
		else if (pre == p->pLeft && p->pRight)
		{
			pre = p;
			p = p->pRight;
		}
		else
		{
			pre = p;
			p = p->pParent;
		}
	}
}
由于本人水平有限,代码中可能有错误,若发现错误请帮忙指出,但思路应该是没问题的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值