时间:2023-03-09来源:系统城装机大师作者:佚名
前序遍历的顺序是根、左、右。任何一颗树都可以认为分为左路节点,左路节点的右子树。先访问左路节点,再来访问左路节点的右子树。把访问左路节点的右子树看成一个子问题,就可以完整递归访问了。
先定义栈st存放节点、v
存放值,TreeNode* cur
,cur初始化为root。
当cur不为空或者栈不为空的时候(一开始栈是空的,cur不为空),循环继续:先把左路节点存放进栈中,同时把值存入v中,一直循环,直到此时的左路节点为空,访问结束。在弹出栈顶元素top,把top->right赋值给我们的cur,就可以转化成子问题去访问左路节点的右子树了。
cur
不为空说明此时还有树要去访问。当两个同时为空时,循环结束,最终得到前序遍历。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class Solution { public : vector< int > preorderTraversal(TreeNode* root) { vector< int > v; stack<TreeNode*> st; TreeNode*cur = root; while (!st.empty()||cur) { //左路节点 while (cur) { st.push(cur); v.push_back(cur->val); cur = cur->left; } //左路节点右子树 TreeNode* top = st.top(); st.pop(); cur = top->right; //转化成子问题访问右子树 } return v; } }; |
中序遍历是左、根、右。左子树访问完之后才能去访问根。左路节点一直走直到左子树访问完,入栈的过程中不去进行访问(存放数值到v中),当左路节点出栈之后,也就是从栈中弹出进行访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class Solution { public : vector< int > inorderTraversal(TreeNode* root) { vector< int > v; stack<TreeNode*> st; TreeNode*cur = root; while (cur||!st.empty()) { while (cur) { //不访问 st.push(cur); cur = cur->left; } TreeNode*top = st.top(); //进行访问 v.push_back(top->val); st.pop(); cur = top->right; } return v; } }; |
后序的遍历顺序是左、右、根。与前面的相比,比较麻烦,我们需要把左子树和右子树访问完再去访问根。我们定义一个栈,在栈里面取到一个节点时:右子树是否访问过,如果没有访问,迭代子问题访问,如果访问过了,则访问这个根节点,pop出栈
如果top的右子树为空或者右子树已经访问过了(上一个访问节点是右子树的根),那么说明右子树不用访问或者访问过了,可以访问根top;当右子树不为空,且没有访问过,则迭代子问题访问。
通过prev
来判断上一次访问的节点:如果prev
等于top->right
时,表示栈顶节点的右子树已经访问过了,可以弹出栈顶节点并访问它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class Solution { public : vector< int > postorderTraversal(TreeNode* root) { vector< int > v; stack<TreeNode*> st; TreeNode*cur = root; TreeNode*prev = nullptr; while (cur||!st.empty()) { while (cur) { st.push(cur); cur = cur->left; } TreeNode*top = st.top(); //top的右子树为空,或者右子树已经访问过了(上一个访问节点时右子树的根)那么说明右子树不用访问或者访问过了,可以访问根top //右子树不为空,且没有访问, 则迭代子问题访问 if (top->right==nullptr||top->right==prev) { st.pop(); v.push_back(top->val); prev = top; } else { cur = top->right; } } return v; } }; |
二叉树的前序遍历、中序遍历、后序遍历的非递归遍历三种方法都是类似的,差别在于访问栈顶的元素的时机不同,访问控制不同。其中前序和中序大致相同,而后序需要去进行判断栈顶的右子树情况。
2024-07-07
Java框架如何实现非阻塞式编程?2023-03-11
Android Jetpack 组件LiveData源码解析2023-03-11
hbuilderx设置Firefox浏览器安装路径教程 hbuilderx怎么设置Firefox浏览器安装路径?一、AVL树的概念 二、AVL树节点的定义 三、AVL树的插入 四、AVL树的旋转 1.左单旋 2.右单旋 3.左右双旋 4.右左双旋 五、进行验证 六、AVLTree的性能...
2023-03-09