NC45 实现二叉树先序,中序和后序遍历
题意分析:
实现二叉树的先序,中序,后续遍历
题解一(递归遍历):
比如有二叉树
先序遍历:按照访问树根,左子树,右子树的顺序对树进行遍历,子树同样遵守这个遍历顺序
如图所示的二叉树:先序遍历结果为4,2,1,3,5.
代码实现如下:
void preOrder(TreeNode *root, vector<int> &ret) {
if (!root) {
return;
}
ret.push_back(root->val);
preOrder(root->left, ret);
preOrder(root->right, ret);
} 中序遍历:按照访问左子树,树根,右子树的顺序对树进行遍历,子树同样遵守这个遍历顺序
如图所示的二叉树:中序遍历结果为1,2,3,4,5.
代码实现如下:
void inOrder(TreeNode *root, vector<int> &ret) {
if (!root) {
return;
}
inOrder(root->left, ret);
ret.push_back(root->val);
inOrder(root->right, ret);
} 后序遍历:按照访问左子树,右子树,树根的顺序对树进行遍历,子树同样遵守这个遍历顺序
如图所示的二叉树:后序遍历结果为1,3,2,5,4.
代码实现如下:
void posOrder(TreeNode *root, vector<int> &ret) {
if (!root) {
return;
}
posOrder(root->left, ret);
posOrder(root->right, ret);
ret.push_back(root->val);
} 总结:那种遍历就表示什么时候访问根结点,先序表示首先访问根结点。中序表示在中间访问根结点
后序表示最后访问根节点。
三种遍历算法时间复杂度,n为树中结点个数。
空间复杂度:,h为树深。
题解二:(将递归用栈模拟):
递归调用本质上都可以用栈进行模拟。
先序遍历的非递归展开:
vector<int> PreOrderNonRecur(TreeNode *root) {
TreeNode *T = root;
stack<TreeNode *> S;
vector<int> ret;
while (T || !S.empty()) {
while (T) {
ret.push_back(T->val);
S.push(T);
T = T->left;
}
if (!S.empty()) {
T = S.top();
S.pop();
T = T->right;
}
}
return ret;
} 中序遍历的非递归展开:
vector<int> inOrderNonRecur(TreeNode *root) {
TreeNode *T = root;
stack<TreeNode *> S;
vector<int> ret;
while (T || !S.empty()) {
while (T) {
S.push(T);
T = T->left;
}
if (!S.empty()) {
T = S.top();
S.pop();
ret.push_back(T->val);
T = T->right;
}
}
return ret;
} 后序遍历的非递归展开:
后序遍历有点特殊,其访问顺序为左子树-右子树-根,可以利用栈,依次将根-右子树-左子树压栈,在弹出的时候就有这个顺序。先序遍历的顺序为根-左子树-右子树,只要将先序遍历的非递归展开左右先后顺序,最后输出栈中的元素即可。
vector<int> posOrderNonRecur(TreeNode *root) {
TreeNode *T = root;
stack<TreeNode *> S1;
stack<TreeNode *> S2;
while (T || !S1.empty()) {
while (T) {
S2.push(T);
S1.push(T);
T = T->right;
}
if (!S1.empty()) {
T = S1.top();
S1.pop();
T = T->left;
}
}
vector<int> ret;
while (!S2.empty()) {
ret.push_back(S2.top()->val);
S2.pop();
}
return ret;
} 三种遍历算法时间复杂度,n为树中结点个数。
空间复杂度:,h为树深。

京公网安备 11010502036488号