注:本文内容参考左老师课程
二叉树的遍历分为前、中、后序,对于递归的实现方法,这里不再赘述,本文主要介绍实现非递归的方法,其核心思想均是用栈来实现,其中着重说明后序遍历。
前序遍历:相对容易
1 //方法1 2 void preOrderTraversal(TreeNode *root,vector<int> &pre){ 3 stack<TreeNode *> s; 4 TreeNode *p = root; 5 while(!s.empty() || p != NULL){ 6 while(p != NULL){ 7 pre.push_back(p->val); 8 s.push(p); 9 p = p->left; 10 } 11 if(!s.empty()){ 12 p = s.top(); 13 s.pop(); 14 p = p->right; 15 16 } 17 } 18 } 19 //方法2 20 void preOrderTraversal(TreeNode *root,vector<int> &pre){ 21 stack<TreeNode *> s; 22 TreeNode *p = root; 23 s.push(p); 24 while(!s.empty()){ 25 p = s.top(); 26 s.pop(); 27 pre.push_back(p->val); 28 if(p->right) 29 s.push(p->right); 30 if(p->left) 31 s.push(p->left); 32 } 33 }
中序遍历:
1 void inOrderTraversal(TreeNode *root,vector<int> &in){ 2 stack<TreeNode *> s; 3 TreeNode *p = root; 4 while(!s.empty() || p != NULL){ 5 while(p != NULL){ 6 s.push(p); 7 p = p->left; 8 } 9 p = s.top(); 10 in.push_back(p->val); 11 s.pop(); 12 p = p->right; 13 } 14 }
后序遍历:
方法1:使用两个栈实现(把先序访问的顺序用第二个栈存起来,然后再出栈就成了)
具体过程如下:
1.申请两个栈,记为s1,s2,然后将头节点压入s1中
2.从s1中弹出栈顶节点,记为cur,然后先把cur的左孩子压入s1中,然后把cur的右孩子压入s1中
3.在整个过程中,每一个从s1中弹出的节点都放入第二个栈s2中。
4.不断重复步骤2和步骤3,直到s1为空,过程停止。
5.从s2中依次弹出节点并打印,打印的顺序就是后序遍历的顺序了。
代码如下:
1 void postOrderTraversal(TreeNode *root,vector<int> &post){ 2 stack<TreeNode *> s1; 3 stack<TreeNode *> s2; 4 TreeNode *p = root; 5 s1.push(p); 6 while(!s1.empty()){ 7 p = s1.top(); 8 s1.pop(); 9 s2.push(p); 10 if(p->left) 11 s1.push(p->left); 12 if(p->right) 13 s1.push(p->right); 14 } 15 while(!s2.empty()){ 16 post.push_back(s2.top()->val); 17 s2.pop(); 18 } 19 }
方法二:用一个栈来实现
具体过程如下:
- 申请一个栈,记为s,将头节点压入s,同时设置两个变量cur和pre,在整个遍历过程中,cur代表当前s的栈顶节点,pre代表上一次访问的结点,初始时cur为NULL,pre为头节点
- 每次令cur等于当前s的栈顶节点,但不从栈中弹出节点,此时分以下三种情况:
- 如果cur的左孩子不为空,并且pre不等于cur的左孩子,也不等于cur的右孩子(代表左孩子存在,且左右孩子都没有访问过),则把cur的左孩子压入栈s中。
- 如果情况1不成立,并且cur的右孩子不为空,并且pre不等于cur的右孩子(代表其左孩子为空或者其已经访问过,但其右孩子没有访问过),则把cur的右孩子压入栈s中。
- 如果情况1和情况2都不成立,那么从s中弹出cur并打印,然后令pre等于cur。
- 一直重复步骤2,直到s为空,过程停止。
1 void postOrderTraversal(TreeNode *root,vector<int> &post){ 2 stack<TreeNode *> s; 3 TreeNode *cur = NULL; 4 TreeNode *pre = root; //注意这里的值 5 s.push(root); 6 while(!s.empty()){ 7 cur = s.top(); 8 if(cur->left && pre != cur->left && pre != cur->right) 9 s.push(cur->left); 10 else if(cur->right && pre != cur->right) 11 s.push(cur->right); 12 else{ 13 s.pop(); 14 post.push_back(cur->val); 15 pre = cur; 16 } 17 } 18 }