二叉树非递归前序、中序、后序遍历
1.二叉树前序遍历:
节点定义:
//Definition for a binary tree node. struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} };
Leetcode144: https://leetcode.com/problems/binary-tree-preorder-traversal/
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> right_nodes; if(root!=nullptr) right_nodes.push(root); while(!right_nodes.empty()) { TreeNode* node=right_nodes.top(); right_nodes.pop(); res.push_back(node->val); if(node->right!=nullptr) right_nodes.push(node->right); TreeNode* left_son=node->left; while(left_son!=nullptr) { res.push_back(left_son->val); if(left_son->right!=nullptr) right_nodes.push(left_son->right); left_son=left_son->left; } } return res; } };
2.二叉树中序遍历:
Leetcode94: https://leetcode.com/problems/binary-tree-inorder-traversal/
基本思路:
1.将根节点压栈,并从该节点一直走到最左下(一直沿着左孩子走到左孩子非空的节点),途中依次将经过的节点压栈。
2.取栈顶节点,必定已访问过其左节点,输出val,并出栈;
3.若该节点有右孩子,则对右孩子做根节点一样的操作,即将右孩子压栈,并从该节点一直走到最左下(一直沿着左孩子走到左孩子非空的节点),途中依次将经过的节点压栈。
4.返回第2步,直至栈空。
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { stack<TreeNode*> nodes; vector<int> res; if(root!=nullptr) //根节点非空 { //将根节点压栈,并一直遍历到二叉树最左下 nodes.push(root); if(root->left!=nullptr) { TreeNode* left=root->left; while(left!=nullptr) { nodes.push(left); left=left->left; } } } while(!nodes.empty()) { //对于出栈节点,已访问过其左孩子 TreeNode* node=nodes.top(); nodes.pop(); res.push_back(node->val); //若该节点右孩子非空 if(node->right!=nullptr) { //右孩子压栈 TreeNode* right=node->right; nodes.push(right); //该节点左孩子非空,延该节点走到最左下 if(right->left!=nullptr) { TreeNode* left=right->left; while(left!=nullptr) { nodes.push(left); left=left->left; } } } } return res; } };
3.二叉树后序遍历:
Leetcode145: https://leetcode.com/problems/binary-tree-postorder-traversal/
后序遍历除了需要一个辅助栈,还需要给每一个栈中元素一个标记,标记这个节点是否已访问过其左节点和是否已访问过其左右节点。
基本思路:
1.若根节点非空,将其压栈。
2.取栈顶节点
a. 若标记visited==0,说明未访问过该节点的孩子;从该节点一直走到最左下(一直沿着左孩子走到左孩子非空的节点),途中依次将经过的节点压栈,并将压栈节点的标记都置为1(因为访问过其左孩子了)。
b. 若标记visited==1,说明访问过其左孩子,将其右孩子压栈,并将该节点标记置为2,从该节点一直走到最左下(一直沿着左孩子走到左孩子非空的节点),途中依次将经过的节点压栈,并将压栈节点的标记都置为1。
c. 若标记visited==2,说明访问过其左右孩子,则直接输出其val。
3.返回至第2步,直至栈空。
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { vector<int> res; map<TreeNode*, int> visited; stack<TreeNode*> nodes; if(root!=nullptr) nodes.push(root); while(!nodes.empty()) { TreeNode* node=nodes.top(); if(visited.count(node)) { if(visited[node]==2) { //cout<<node->val<<endl; res.push_back(node->val); nodes.pop(); } else ///visit right son { visited[node]=2; if(node->right!=nullptr) { TreeNode* right=node->right; visited[right]=1; nodes.push(right); TreeNode* left=right->left; while(left!=nullptr) { visited[left]=1; nodes.push(left); left=left->left; } } } } else { TreeNode* left=node->left; visited[node]=1; while(left!=nullptr) { visited[left]=1; nodes.push(left); left=left->left; } } } return res; } };