树的遍历【根据前序和中序遍历的结果确定后序遍历结果】

问题分析

  1. 条件:已知前序遍历结果数组Pre[]和中序遍历结果数组Mid[]。
  2. 目标:确定后序遍历结果数组Post[]。
  3. 三种遍历结果之间的关联:
    三种遍历结果的结构如下图所示:
    在这里插入图片描述
    对上图进行分析,可以确定Pre[]和Mid[]在求解Post[]中各自发挥的作用:Pre[]的作用为找到根节点root, Mid[]的作用为根据当前root划分左右子树用于递归求解。

算法思路

  1. 首先在Pre[]中找到root(即为pre的首元素),将root值填到Post[]中对应存放root的位置;
  2. 在Mid[]中找到root的位置,其左右两侧即为作、右子树;
  3. 递归求解左、右子树,直至子树节点数为0或1。

算法实现

/*
Parameters:
Pre, Mid: 存储PreOrder, MidOrder结果的数组(已知);
Post: 存储PostOrder结果的数组(目标);
PreL, MidL, PostL: 当前处理的子树节点在Pre[],Mid[],Post[]中分别对应的起始位置;
Length: 当前处理的子树具有的节点数目。
*/
void BinaryTree::CalPostOrder(int* Pre, int* Mid, int* Post, int PreL, int MidL, int PostL, int length) {
	if (length == 0) return; // 子树节点数为0,结束递归
	if (length == 1) { // 子树只有一个节点,Pre[PreL], Mid[MidL], Post[PostL]都对应相同的数据,直接赋值即可
		Post[PostL] = Pre[PreL];
		return;
	}
	int RootData = Pre[PreL]; //找到root
	Post[PostL + length - 1] = RootData; //给Post[]赋值
	int i = 0;
	for (; i < length; i++) {
		if (Mid[MidL + i] == RootData) break; //找到 Mid[]中root的位置
	}
	int LeftLength = i; //左子树节点数
	int RightLength = length - 1 - i; //右子树节点数
	CalPostOrder(Pre, Mid, Post, PreL + 1, MidL, PostL, LeftLength); //求解左子树
	CalPostOrder(Pre, Mid, Post, PreL + 1 + LeftLength, MidL + 1 + LeftLength, PostL + LeftLength, RightLength); //求解右子树
}

算法测试

在0-100范围内随机产生10个正整数,将其插入树,分别进行前序、中序、后序遍历,再根据前序和中序的结果计算后序遍历结果,测试结果如下:
在这里插入图片描述
将两种后序遍历结果进行对比,可以看出两种方式得到的后序遍历结果是相同的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
的深度优先遍历包括前序遍历中序遍历后序遍历,它们的遍历顺序规则分别为: 前序遍历(Preorder traversal):遍历顺序规则为【DLR | 即当前结点, 左孩子, 右孩子】。 中序遍历(Inorder Traversal):遍历顺序规则为【LDR | 即左孩子, 当前结点, 右孩子】。 后序遍历(Postorder Traversal):遍历顺序规则为【LRD | 即左孩子, 右孩子, 当前结点】。 因此,深度优先遍历不是前序遍历中序遍历后序遍历的统称,而是包括了这三种遍历方式。 下面是C++代码实现: 递归实现: ```c++ // 前序遍历 void preorder(TreeNode* root) { if (root == nullptr) { return; } cout << root->val << " "; preorder(root->left); preorder(root->right); } // 中序遍历 void inorder(TreeNode* root) { if (root == nullptr) { return; } inorder(root->left); cout << root->val << " "; inorder(root->right); } // 后序遍历 void postorder(TreeNode* root) { if (root == nullptr) { return; } postorder(root->left); postorder(root->right); cout << root->val << " "; } ``` 非递归实现: ```c++ // 前序遍历 void preorder(TreeNode* root) { if (root == nullptr) { return; } stack<TreeNode*> s; s.push(root); while (!s.empty()) { TreeNode* node = s.top(); s.pop(); cout << node->val << " "; if (node->right != nullptr) { s.push(node->right); } if (node->left != nullptr) { s.push(node->left); } } } // 中序遍历 void inorder(TreeNode* root) { if (root == nullptr) { return; } stack<TreeNode*> s; TreeNode* node = root; while (node != nullptr || !s.empty()) { while (node != nullptr) { s.push(node); node = node->left; } node = s.top(); s.pop(); cout << node->val << " "; node = node->right; } } // 后序遍历 void postorder(TreeNode* root) { if (root == nullptr) { return; } stack<TreeNode*> s1, s2; s1.push(root); while (!s1.empty()) { TreeNode* node = s1.top(); s1.pop(); s2.push(node); if (node->left != nullptr) { s1.push(node->left); } if (node->right != nullptr) { s1.push(node->right); } } while (!s2.empty()) { cout << s2.top()->val << " "; s2.pop(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值