Loading

二叉树的遍历

二叉树的结构:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */

 

建议使用下图这个例子:

 

二叉树先中后序遍历(递归实现)

 1 //递归实现中序遍历
 2 void InorderTraversal(TreeNode* root)
 3 {
 4     if(root)   //如果不是空树
 5     {
 6         InorderTraversal(root->Left);
 7         printf("%d", root->val);       //此处假设对BT节点的访问就是打印数据
 8         InorderTraversal(root->right);
 9     }
10 
11 }
12 
13 
14 //递归实现先序遍历
15 void PreorderTraversal(TreeNode* root)
16 {
17     if(root)   //如果不是空树
18     {
19         printf("%d", root->val);
20         PreorderTraversal(root->left);
21         PreorderTraversal(root->right);
22     }
23 }
24 
25 
26 //递归实现后序遍历
27 void PostorderTraversal(TreeNode* root)
28 {
29     if(root)   //如果不是空树
30     {
31         PostorderTraversal(root->left);
32         PostorderTraversal(root->right);
33         printf("%d", root->val);
34     }
35 }

 

非递归实现中序遍历

 1 class Solution {
 2 public:
 3     vector<int> inorderTraversal(TreeNode* root) {
 4         vector<int> res;
 5         if(root == NULL) {
 6             return res;
 7         }
 8 
 9         stack<TreeNode*> S;
10         //根结点入栈
11         S.push(root);
12 
13         TreeNode* t = root;
14         //将左孩子全部入栈
15         while(t->left) {
16             S.push(t->left);
17             t = t->left;
18         }
19 
20         
21         while(!S.empty()) {    
22             //pop出一个结点,并且将其对应的值加入答案数组
23             t = S.top();
24             S.pop();
25             res.push_back(t->val);
26             
27             //如果此结点有右孩子,则将右孩子入栈
28             if(t->right) {
29                 S.push(t->right);
30                 t = t->right;
31 
32                 //将左孩子全部入栈
33                 while(t->left) {
34                     S.push(t->left);
35                     t = t->left;
36                 }
37             }
38         }
39 
40         return res;
41 
42     }
43 };

 

非递归实现先序遍历

方式一:跟上述非递归中序遍历很像很像的代码。区别在于,中序是出栈的时候加入答案数组,先序是入栈的时候加入答案数组。

 1 class Solution {
 2 public:
 3     vector<int> preorderTraversal(TreeNode* root) {
 4         vector<int> res;
 5         if(root == NULL) {
 6             return res;
 7         }
 8 
 9         stack<TreeNode*> S;
10         //根结点入栈,并且将其对应的值加入答案数组
11         S.push(root);
12         res.push_back(root->val);
13 
14         TreeNode* t = root;
15         //将左孩子全部入栈,并且将其对应的值加入答案数组
16         while(t->left) {
17             S.push(t->left);
18             res.push_back(t->left->val);
19             t = t->left;
20         }
21 
22 
23         while(!S.empty()) {
24             //pop出一个结点
25             t = S.top();
26             S.pop();
27             
28             //如果此结点有右孩子,则将右孩子入栈,并且将其对应的值加入答案数组
29             if(t->right) {
30                 S.push(t->right);
31                 res.push_back(t->right->val);
32                 t = t->right;
33 
34                 //将左孩子全部入栈,并且将其对应的值加入答案数组
35                 while(t->left) {
36                     S.push(t->left);
37                     res.push_back(t->left->val);
38                     t = t->left;
39                 }
40             }
41         }
42 
43         return res;
44     }
45 };

 

方法二:

 1 class Solution {
 2 public:
 3     vector<int> preorderTraversal(TreeNode* root) {
 4         vector<int> res;
 5         if(root == NULL) {
 6             return res;
 7         }
 8 
 9         stack<TreeNode*> S;
10         //根结点入栈
11         S.push(root);
12         TreeNode* t = root;
13 
14         while(!S.empty()) {
15             //pop出一个结点,并且将其对应的值加入答案数组
16             t = S.top();
17             res.push_back(t->val);
18             S.pop();
19             
20             //先把右孩子入栈,因为栈是后进先出 
21             if(t->right) {
22                 S.push(t->right);
23             }
24 
25             // 再把左孩子入栈
26             if(t->left) {
27                 S.push(t->left);
28             }
29         }
30 
31         return res;
32     }
33 };

 

非递归实现后序遍历

因为后序非递归遍历二叉树的顺序是先访问左子树,再访问右子树,最后访问根节点。当用堆栈来存储节点,必须分清返回根节点时,是从左子树返回的,还从右子树返回的。

所以,使用辅助指针r,其指向最近访问过的节点。也可以在节点中增加一个标志域,记录是否已被访问。

 1 //非递归实现后序遍历
 2 void PostOrder3(BinTree BT)     
 3 {
 4     BinTree T = BT, r = NULL;   //r用来标记最近访问过的节点
 5     stack<TNode *> s;
 6     while (T || !s.empty())
 7     {
 8         if (T)  //T非空时,遇到一个节点就把这个节点入栈,走到最左边
 9         {
10             s.push(T);
11             T = T->Left;
12         }
13         else
14         {
15             T = s.top();
16             if (T->Right && T->Right != r)//右子树存在且未被访问
17                 T = T->Right;
18             else
19             {
20                 s.pop();
21                 printf("%d", T->Data);
22                 r = T;       //记录最近访问过的节点
23                 T = NULL;    //节点访问完后,重置T指针
24             }
25         }//else
26     }//while
27 
28 }

 

补充一个bug级二叉树非递归遍历的写法

 先序遍历:

 1 /**
 2  * Definition for a binary tree node.
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 
11 struct Command {
12     string s;   // go, print二者之一
13     TreeNode* node;
14     Command(string s, TreeNode* node): s(s), node(node) {}
15 };
16 
17 class Solution {
18 public:
19     vector<int> preorderTraversal(TreeNode* root) {
20         vector<int> res;
21         if(root == NULL)
22             return res;
23         
24         stack<Command> stack;
25         stack.push( Command("go", root) );
26         while( !stack.empty() ) {
27             
28             Command command = stack.top();
29             stack.pop();
30 
31             if( command.s == "print" )
32                 res.push_back( command.node -> val );
33             else {
34                 // 先序遍历是先输出,然后遍历左孩子,然后右孩子
35                 // 所以先把右孩子入栈,再把左孩子入栈,再把输出入栈
36                 assert( command.s == "go" );
37                 if( command.node -> right )
38                     stack.push( Command("go", command.node -> right) );
39                 if( command.node -> left )
40                     stack.push( Command("go", command.node -> left) );
41                 stack.push( Command("print", command.node) );
42             }
43         }
44 
45         return res;
46     }
47 };

中序遍历:

 1 /**
 2  * Definition for a binary tree node.
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 
11 struct Command {
12     string s;   // go, print二者之一
13     TreeNode* node;
14     Command(string s, TreeNode* node): s(s), node(node) {}
15 };
16 
17 class Solution {
18 public:
19     vector<int> inorderTraversal(TreeNode* root) {
20         vector<int> res;
21         if(root == NULL)
22             return res;
23         
24         stack<Command> stack;
25         stack.push( Command("go", root) );
26         while( !stack.empty() ) {
27             
28             Command command = stack.top();
29             stack.pop();
30 
31             if( command.s == "print" )
32                 res.push_back( command.node -> val );
33             else {
34                 // 中序遍历是先遍历左孩子,然后输出,最后右孩子
35                 // 所以先把右孩子入栈,再把输出入栈,再把左孩子入栈
36                 assert( command.s == "go" );
37                 if( command.node -> right )
38                     stack.push( Command("go", command.node -> right) );
39                 stack.push( Command("print", command.node) );
40                 if( command.node -> left )
41                     stack.push( Command("go", command.node -> left) );
42             }
43         }
44         return res;
45     }
46 };

后序遍历:

 1 /**
 2  * Definition for a binary tree node.
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 
11 struct Command {
12     string s;   // go, print二者之一
13     TreeNode* node;
14     Command(string s, TreeNode* node): s(s), node(node) {}
15 };
16 
17 class Solution {
18 public:
19     vector<int> postorderTraversal(TreeNode* root) {
20         vector<int> res;
21         if(root == NULL)
22             return res;
23         
24         stack<Command> stack;
25         stack.push( Command("go", root) );
26         while( !stack.empty() ) {
27             
28             Command command = stack.top();
29             stack.pop();
30 
31             if( command.s == "print" )
32                 res.push_back( command.node -> val );
33             else {
34                 // 后序遍历是先遍历左孩子,然后右孩子,最后输出
35                 // 所以先把输出入栈,再把右孩子入栈,再把左孩子入栈
36                 assert( command.s == "go" );
37                 stack.push( Command("print", command.node) );
38                 if( command.node -> right )
39                     stack.push( Command("go", command.node -> right) );
40                 if( command.node -> left )
41                     stack.push( Command("go", command.node -> left) );
42             }
43         }
44         return res;
45     }
46 };

 

二叉树的层序遍历:

(1) 从队列中取出一个元素;

(2) 访问该元素所指节点;

(3) 若该元素所指节点的左右孩子节点非空,则将其左右孩子节点顺序入队。

不断执行这三步操作,直到队列为空,再无元素可取,二叉树的层序遍历就完成了。

 

 1 class Solution {
 2 public:
 3     vector<vector<int>> levelOrder(TreeNode* root) {
 4         vector<vector<int>> res;
 5         if(root == NULL)
 6             return res;
 7 
 8         queue<TreeNode *> Q;
 9         Q.push(root);
10 
11         while(!Q.empty()) {
12             vector<int> v;
13             int qsize = Q.size();
14 
15             for(int i = 0; i < qsize; ++i) {
16                 TreeNode *t = Q.front();
17                 Q.pop();
18                 v.push_back(t->val);
19 
20                 if(t->left)
21                     Q.push(t->left);
22                 if(t->right)
23                     Q.push(t->right);
24             }
25 
26             res.push_back(v);
27         }
28 
29         return res;
30     }
31 };

 

posted @ 2018-09-29 16:19  拾月凄辰  阅读(129)  评论(0编辑  收藏  举报