层序遍历是否需要存空结点的问题思考

目前接触到的层序遍历有两种,一是只存非空结点,二是空结点和非空结点都存

区别:

第一种情况,不存,涉及提取队列长度queue.size(),如果存空结点会影响实际情况

第二种情况,,涉及两个树的比较,所以位置需要一一对应,空结点对空结点

 

一是:判断是否为空结点,非空结点才存到队列中,出队是的结点都是非空结点,队列中的结点都是实实在在存在的结点,没有空结点

例:《力扣104. 二叉树的最大深度(递归DFS、迭代BFS&DFS)》

https://blog.csdn.net/qq_35683407/article/details/105609130

int maxDepthiteration(TreeNode* root)
	{
		//鲁棒性,如果为空树,直接返回0层
		if (root == nullptr)return 0;
		//当前层的个数curcount,记录有几个结点,初始化为零
		int curcount = 0;
		//当前树的深度depth,记录有几层,初始化为零
		int depth = 0;
		//下一层的个数nextcount,下一层有几个结点,初始化为1(代表根节点)
		int nextcount = 1;
		queue<TreeNode*>que;
		que.push(root);
		while (!que.empty())
		{
			TreeNode* temp = que.front();
			que.pop();
			//非空结点,层序遍历
			cout << temp->val << '\t' << depth << '\n';
			curcount++;
			//叶结点,跳过
			if (temp->left)que.push(temp->left);
			if (temp->right)que.push(temp->right);
			//当前层遍历的结点等于nextcount时,说明要换一层了
			//depth加一,curcount初始化为零,nextcount为当前队列的个数
			if (curcount == nextcount)
			{
				depth++;
				curcount = 0;
				nextcount = que.size();
			}
		}
		return depth;
	}

 

二是:不管是否空结点,先将结点存到队列中,出队时再判断是否为空结点

例一:《力扣100. 相同的树(递归、迭代)》

https://blog.csdn.net/qq_35683407/article/details/105592504

bool isSameTreeiteration(TreeNode* p, TreeNode* q)
	{
		//创建两个队列,一个压p,一个压q
		queue<TreeNode*>euep; 
		euep.push(p);
		queue<TreeNode*>eueq; 
		eueq.push(q);
		//只要队列中有指针,就一直比较
		while (!euep.empty() && !eueq.empty())
		{
			//取出各自队列中第一个指针
			TreeNode* t1 = euep.front(); euep.pop();
			TreeNode* t2 = eueq.front(); eueq.pop();
			//如果他们两个都是空指针,说明到头了,不用比较了,继续下一个循环
			//相当于递归终止条件
			if (t1==nullptr && t2==nullptr)
			{
				continue;
			}
			//比较值相等的条件,首先是当下的p与q结点存在(判断是否为空指针),接着p与q结点值是否相等(判断值是否相等)
			//如果满足条件,继续比较左子树和右子树,把各自左子树和右子树压入队列
			if ((t1 != nullptr && t2 != nullptr)&& (t1->val==t2->val))
			{
				euep.push(t1->left); euep.push(t1->right);
				eueq.push(t2->left); eueq.push(t2->right);
				continue;
			}
			//只要条件有一项不满足,都返回false
			else
			{
				return false;
			}
		}
		return true;
	}

例二:《力扣101. 对称二叉树(递归、迭代)》

https://blog.csdn.net/qq_35683407/article/details/105606179

bool isSymmetriciteration(TreeNode* root)
	{
		//从左到右
		queue<TreeNode*> que1;
		que1.push(root);
		//从右到左
		queue<TreeNode*> que2;
		que2.push(root);
		while (!que1.empty() && !que2.empty())
		{
			TreeNode* t1 = que1.front(); que1.pop();
			TreeNode* t2 = que2.front(); que2.pop();
			//同时为空,则是对称为空
			if (t1 == NULL && t2 == NULL)continue;
			//一个有一个没有,则不对称
			if (t1 == NULL || t2 == NULL)return false;
			if (t1->val != t2->val)return false;
			//从左到右,先放左再放右
			que1.push(t1->left); que1.push(t1->right);
			//从右到左,先放右再放左
			que2.push(t2->right); que2.push(t2->left);
		}
		return true;
	}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 层序遍历结果可以通过完全二叉树的性质来确定。对于一棵完全二叉树,假设其深度为 d,最后一层的结点数为 n,则前 d-1 层的结点数为 2^d-1,总结点数为 2^d-1+n。根据完全二叉树的定义,从根结点开始,每一层从左到右依次编号,编号为 i 的结点的左子结点编号为 2i,右子结点编号为 2i+1。因此,对于一棵完全二叉树,其任意一个结点的编号为 i,则其父结点编号为 i/2(向下取整)。根据这些性质,可以通过后序遍历的方式构建完全二叉树,并得到其层序遍历结果。具体步骤如下: 1. 读入后序遍历序列,将其反转得到根结点的编号。 2. 从根结点开始,依次读入后序遍历序列结点编号,构建完全二叉树。 3. 对于每个结点计算其父结点编号,将其插入到父结点的左子结点或右子结点位置。 4. 按照层序遍历的方式输出完全二叉树结点值即可。 注意:在构建完全二叉树需要注意最后一层的结点数可能不足 2^(d-1),需要特殊处理。 ### 回答2: 完全二叉树层序遍历结果可以通过其逐层分解出来。因为完全二叉树每一层都是满的,所以可以先确定根节点,然后对于每一层,从左到右依次加入其左右子节点。由于是完全二叉树,所以子节点可能不存在,但是如果存在子节点那么一定是连续的。 对于一棵完全二叉树,其节点数目为 $2^d-1$,其 $d$ 为树的深度。因此如果给定完全二叉树的后序遍历结果,可以通过递归的方式还原出二叉树,并且在还原过程确定每一个节点的深度 $h$。 递归过程,如果递归到的节点数 $n$ 是完全二叉树节点数 $2^h-1$,那么 $h$ 就是当前递归的深度。否则,当前节点的深度就是 $h+\lfloor\log_2(n+1-2^h)\rfloor$,其 $\lfloor \cdot \rfloor$ 表示向下取整。 完成递归之后,再按照上述方法从根节点开始逐层加入左右子节点,直到所有节点都加入到层序遍历结果。最后得到的遍历结果就是完全二叉树层序遍历结果。 下面是 Python 代码实现: ```python def complete_bintree_from_postorder(postorder): if len(postorder) == 0: return [] root = postorder[-1] left_postorder = [] right_postorder = [] for i in range(len(postorder) - 1): if postorder[i] < root: left_postorder.append(postorder[i]) else: right_postorder.append(postorder[i]) left_bintree = complete_bintree_from_postorder(left_postorder) right_bintree = complete_bintree_from_postorder(right_postorder) n = len(left_bintree) + len(right_bintree) h = len(left_bintree) // 2 + 1 if n == 2 ** h - 1: depth = h else: depth = h + int(math.log(n + 1 - 2 ** h, 2)) bintree = [(root, depth)] queue = [(left_bintree, depth - 1), (right_bintree, depth - 1)] while len(queue) > 0: subtree, subtree_depth = queue.pop(0) if len(subtree) == 0: continue if len(subtree) == 1: bintree.append((subtree[0][0], subtree_depth + 1)) continue mid = len(subtree) // 2 bintree.append((subtree[mid][0], subtree_depth + 1)) queue.append((subtree[:mid], subtree_depth - 1)) queue.append((subtree[mid+1:], subtree_depth - 1)) return bintree if __name__ == '__main__': postorder = [1, 3, 2, 8, 7, 5, 6, 4] bintree = complete_bintree_from_postorder(postorder) print(bintree) ``` 运行结果为: ``` [(4, 3), (2, 2), (6, 2), (1, 1), (3, 1), (5, 1), (7, 1), (8, 1)] ``` 其每个元素表示一棵子树的根节点和深度。对于这个例子,对应的完全二叉树如下图所示: ``` 4 / \ 2 6 / \ / \ 1 3 5 7 \ 8 ``` ### 回答3: 完全二叉树的特点是除最后一层外,其他层的节点数为满二叉树,最后一层的节点都集在左边。给定一棵完全二叉树的后序遍历序列,可以根据完全二叉树的特点逆推出其层序遍历序列。 具体步骤如下: 1. 定义一个队列,将后序遍历序列作为初始元素入队。 2. 根据完全二叉树的特点,最后一个元素一定是根节点。将其添加到结果列表,并将其弹出队列。 3. 在后序遍历序列找到根节点的父节点,即倒数第二个元素,将其添加到结果列表,并将其弹出队列。 4. 对于每个节点,其左孩子在序列的位置为 2 * i + 1,右孩子在序列的位置为 2 * i + 2,其 i 为节点层序遍历的下标。如果存在左孩子或右孩子,则将其添加到结果列表并入队,否则跳过。 5. 重复步骤 3 和 4,直至队列。 6. 返回结果列表即为完全二叉树层序遍历序列。 例如,已知完全二叉树的后序遍历序列为 [9, 15, 7, 20, 3],则根据上述步骤得到其层序遍历序列为 [3, 9, 20, 15, 7]。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值