二叉树的遍历

* 先根序遍历(非递归版)

 1 void PreOrder(TreeNode* root)
 2 { 
 3         stack<TreeNode*> s;
 4         TreeNode *p=root,*last_visit=NULL;
 5         while(p||s.size()>0)
 6         {
 7             if(p)//走到最左 边走边访问 并进栈
 8             {
 9                 cout<<p->val<<endl;
10                 s.push(p);
11                 p=p->left;
12             }
13             else//左边没有节点了
14             {
15                 p=s.top();//弹出上一个节点
16                 s.pop();
17                 p=p->right;//转向右子树
18             }
19         }        
20 }

* 中根序遍历(非递归版)

void InOrder(TreeNode* root)
{       
        stack<TreeNode*> s;
        TreeNode *p=root,*last_visit=NULL;
        while(p||s.size()>0)
        {
            if(p)//走到最左
            {
                s.push(p);
                p=p->left;
            }
            else//左边没有节点了
            {
                p=s.top();//弹出上一个节点
                s.pop();
                cout<<p->val<<endl;//访问栈中弹出的节点
                p=p->right;//转向右子树
            }
        }     
}

* 后根序遍历(非递归版)

 1 void PostOrder(TreeNode* root)
 2 {
 3         stack<TreeNode*> s;
 4         TreeNode *p=root,*last_visit=NULL;//last_visit指针记录上次访问过的值,因为后根序 根节点最后访问 所以未访问根节点时 根节点还未退栈 所以需要判别右子树是否访问过
 5         while(p||s.size()>0)
 6         {
 7             if(p)//走到最左
 8             {
 9                 s.push(p);
10                 p=p->left;
11             }
12             else//左边没有节点了
13             {
14                 p=s.top();//弹出上一个节点
15                 if(p->right&&p->right!=last_visit)//若上一个节点存在右子树 且 未被访问过 则转向右子树
16                 {
17                     s.push(p->right);//右子树进栈
18                     p=p->right->left;//再转向右子树的左子树
19                 }
20                 else//p的左右子树都不存在才进行访问
21                 {
22                     last_visit=s.top();//记录下来本节点已经访问过了
23                     cout<<s.top()->val<<endl;
24                     s.pop();//将访问过的节点退栈
25                     p=NULL;//指针指向空 下次进来判断栈内下一个元素
26                 }
27             }
28         }       
29 } 

* 二叉树的层次遍历(利用队列)

 1 void LevelOrder(TreeNode * root)
 2 {        
 3         queue<TreeNode*> que;//队列
 4         TreeNode* p;
 5         que.push(root);//先将根节点放入队列
 6         while(!que.empty())//队列不空
 7         {
 8             p=que.front();//取出队头结点
 9             cout<<p->val<<endl;//访问队头结点
10             que.pop();//将队头结点从队列中移除
11             if(p->left)//若p存在左子树
12                 que.push(p->left);
13             if(p->right)//若p存在右子树
14             que.push(p->right);
15         }
16 }  

应用:

1、利用层次遍历 获得二叉树的深度

 1 int GetBiTDepth(TreeNode* root)
 2 {    if(!root) return 0;
 3         queue<TreeNode*> que;
 4         TreeNode* p=root,*last=root;//初始化第一层最后一个节点为root
 5         que.push(p);
 6         int count=0;//记录层数
 7         while(!que.empty())//队列不空
 8         {
 9             p=que.front();//取出队头结点
10             que.pop();//将队头结点从队列中移除
11             if(p->left)//若p存在左子树
12                 que.push(p->left);
13             if(p->right)//若p存在右子树
14                 que.push(p->right);
15             if(p==last)
16             {
17                 count++;//若遇到本层最后一个节点 层数+1
18                 last=que.back();//下一层最后一个节点为队列的尾部
19             }
20         }
21         return count;
22 }

2、递归求树的深度

 int GetBiTDepth(TreeNode* root)
    {
        if(root==NULL) return 0;
        else
        {
          int leftDepth=GetBiTDepth(root->left);
          int rightDepth=GetBiTDepth(root->right);
          return leftDepth>rightDepth?leftDepth+1:rightDepth+1;//树的深度为子树的最大高度加根节点
        }      
    }

3、leetcode 107题  给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

 1 //法1 利用stl中的queue库    
 2 vector<vector<int>> levelOrderBottom(TreeNode* root) {
 3         vector<vector<int>> result;
 4         if(!root) return result;
 5         queue<TreeNode*> que;
 6         TreeNode* p=root,*last=root;//初始化第一层最后一个节点为root
 7         que.push(p);
 8         vector<int> level_result;
 9         while(!que.empty())//队列不空
10         {
11             p=que.front();//取出队头结点
12             level_result.push_back(p->val);
13             que.pop();//将队头结点从队列中移除
14             if(p->left)//若p存在左子树
15                 que.push(p->left);
16             if(p->right)//若p存在左子树
17                 que.push(p->right);
18             if(p==last)
19             {
20                 result.push_back(level_result);
21                 level_result.clear();
22                 last=que.back();//下一层最后一个节点为队列的尾部
23             }
24         }
25         reverse(result.begin(),result.end());
26         return result;
27     }
 1     //法2 利用数组模拟queue
 2     vector<vector<int>> levelOrderBottom(TreeNode* root) {
 3         vector<vector<int>> result;
 4         vector<int> level_result;
 5         if(!root) return result;
 6         TreeNode* queue[10000];
 7         TreeNode *p;
 8         int rear=-1,front=-1;
 9         int last=0;//代表每一层的最后一个
10         queue[++rear]=root;
11         while(front<rear)//队列不空
12         {
13             p=queue[++front];//将队头结点从队列中移除
14             level_result.push_back(p->val);
15             if(p->left)//若p存在左子树
16                 queue[++rear]=p->left;
17             if(p->right)//若p存在右子树
18                 queue[++rear]=p->right;
19             if(front==last)//当前节点是本层最后一个
20             {
21                 result.push_back(level_result);
22                 level_result.clear();
23                 last=rear;//下一层最后一个节点为队列的尾部
24             }
25         }
26         reverse(result.begin(),result.end());//逆置
27         return result;
28     }

4、leetcode 第105题 根据一棵树的前序遍历与中序遍历构造二叉树

 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 class Solution {
12 public:
13     TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
14        if(preorder.empty())return NULL;
15        return buildTreeHelper(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
16     }
17     TreeNode* buildTreeHelper(vector<int>& preorder, vector<int>& inorder,int ps,int pe,int is,int ie)
18     {
19         //ps pe分别为 preorder 的第一个元素的下标和最后一个元素的下标
20         //is ie分别为 inorder 的第一个元素的下标和最后一个元素的下标
21 
22         TreeNode* node=new TreeNode(preorder[ps]);
23         int cut;//中根序 根节点所在的地方 
24         for(cut=is;cut<ie&&inorder[cut]!=preorder[ps];cut++);//找到分割点
25         int l_len=cut-is;//左子树长度
26         int r_len=ie-cut;//右子树长度
27 
28         // cout<<cut<<" "<<l_len<<" "<<r_len<<" "<<endl;
29         // print_vector(preorder,ps+1,ps+l_len);//先根序序列 左子树的部分
30         // print_vector(inorder,is,is+l_len-1);//中根序序列 左子树的部分
31         // print_vector(preorder,pe-r_len+1,pe);//先根序序列 右子树的部分
32         // print_vector(inorder,ie-r_len+1,ie);//中根序序列 右子树的部分
33 
34         if(l_len) //若存在左子树 则对左子树进行递归
35             node->left=buildTreeHelper(preorder,inorder,ps+1,ps+l_len,is,is+l_len-1);
36         else 
37             node->left=NULL;
38         if(r_len) //若存在右子树 则对右子树进行递归
39             node->right=buildTreeHelper(preorder,inorder,pe-r_len+1,pe,ie-r_len+1,ie);
40         else 
41             node->right=NULL;
42         return node;
43     }
44     // void print_vector(vector<int>& v,int s,int e)
45     // {
46     //     int i=s;
47     //     for(;i<=e;i++)
48     //         cout<<v[i]<<" ";
49     //     cout<<endl;
50     // }
51 };

5、leetcode 第106题 根据一棵树的中序遍历与后序遍历构造二叉树

 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  //后序遍历列表最后一个节点为根节点 
12  //在中序中 根节点前的是左子树(is,is+l_len-1) 根节点右边的是右子树(ie-r_len+1,ie)
13  //在后序中 (pe-1-r_len+1,pe-1)为右子树,(ps,ps+l_len-1)为左子树
14 class Solution {
15 public:
16 TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
17        if(postorder.empty())return NULL;
18        return buildTreeHelper(inorder,postorder,0,inorder.size()-1,0,postorder.size()-1);
19     }
20     TreeNode* buildTreeHelper(vector<int>& inorder, vector<int>& postorder,int is,int ie,int ps,int pe)
21     {
22         //is ie分别为 inorder 的第一个元素的下标和最后一个元素的下标
23         //ps pe分别为 postorder 的第一个元素的下标和最后一个元素的下标
24       
25         TreeNode* node=new TreeNode(postorder[pe]);
26         int cut;//中根序 根节点所在的地方 
27         for(cut=is;cut<ie&&inorder[cut]!=postorder[pe];cut++);//找到分割点
28         int l_len=cut-is;//左子树长度
29         int r_len=ie-cut;//右子树长度
30 
31         // cout<<cut<<" "<<l_len<<" "<<r_len<<" "<<endl;
32         // print_vector(postorder,ps,ps+l_len-1);//后根序序列 左子树的部分
33         // print_vector(inorder,is,is+l_len-1);//中根序序列 左子树的部分
34         // print_vector(postorder,pe-r_len,pe-1);//后根序序列 右子树的部分
35         // print_vector(inorder,ie-r_len+1,ie);//中根序序列 右子树的部分
36 
37         if(l_len) //若存在左子树 则对左子树进行递归
38             node->left=buildTreeHelper(inorder,postorder,is,is+l_len-1,ps,ps+l_len-1);
39         else 
40             node->left=NULL;
41         if(r_len) //若存在右子树 则对右子树进行递归
42             node->right=buildTreeHelper(inorder,postorder,ie-r_len+1,ie,pe-r_len,pe-1);
43         else 
44             node->right=NULL;
45         return node;
46     }
47     // void print_vector(vector<int>& v,int s,int e)
48     // {
49     //     int i=s;
50     //     for(;i<=e;i++)
51     //         cout<<v[i]<<" ";
52     //     cout<<endl;
53     // }
54 };

6、leetcode 第958题 二叉树完全性检验

 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 class Solution {
12 public:
13     bool isCompleteTree(TreeNode* root) {
14         TreeNode* queue[200],*p;
15         int rear=-1,front=-1;
16         queue[++rear]=root;
17         while(front<rear)
18         {
19             p=queue[++front];
20             if(p)//若节点非空 入队
21             {
22                 queue[++rear]=p->left;
23                 queue[++rear]=p->right;
24             }
25             else//若节点为空 则判别队列中是否有非空节点 有则不是完全二叉树
26             {
27                 while(front<rear)
28                 {
29                     p=queue[++front];
30                     if(p) return false;
31                 }
32             }
33         }
34         return true;
35     }
36 };

7、递归统计二叉树的叶子节点数、双分支节点数、单分支节点数、所有节点数

 1 class Solution {
 2 public:
 3     //递归统计所有节点
 4     int countNodes(TreeNode* root) {
 5        if(root==NULL) return 0;//如果节点为空
 6        else if(root->left||root->right) return countNodes(root->left)+countNodes(root->right)+1;//如果存在左子树或右子树
 7        else return 1;//如果不存在左右子树
 8     }
 9      //递归统计所有双分支节点
10     int countNodes(TreeNode* root) {
11        if(root==NULL) return 0;//如果节点为空 
12        else if(root->left&&root->right) return countNodes(root->left)+countNodes(root->right)+1;//如果存在左子树右子树
13        else return countNodes(root->left)+countNodes(root->right);//如果不同时存在左右子树
14     }
15      //递归统计所有单分支节点
16     int countNodes(TreeNode* root) {
17        if(root==NULL) return 0;//如果节点为空 
18        else if((root->left&&!root->right)||(!root->left&&root->right)) 
19            return countNodes(root->left)+countNodes(root->right)+1;//如果左右子树不同时存在
20        else return countNodes(root->left)+countNodes(root->right);//如果不存在左右子树或同时存在左右子树
21     }
22      //递归统计所有叶子节点
23     int countNodes(TreeNode* root) {
24        if(root==NULL) return 0;//如果节点为空 
25        else if(!root->left&&!root->right) return 1;//如果节点没有孩子
26         else return countNodes(root->left)+countNodes(root->right);//如果节点有孩子
27     }
28 };

8、leetcode 第226题 翻转二叉树

 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 class Solution {
11 public:
12     TreeNode* invertTree(TreeNode* root) {
13         if(!root) return NULL;
14         TreeNode* temp=root->left;
15         root->left=invertTree(root->right);//左孩子等于递归交换的右子树
16         root->right=invertTree(temp);//右孩子等于递归交换的左子树
17         return root;
18     }
19 };
原文地址:https://www.cnblogs.com/lancelee98/p/11647662.html