zoukankan      html  css  js  c++  java
  • 二叉树的遍历

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

     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 };
  • 相关阅读:
    .net core 经典面试题
    面试常问概念类问题
    常见 .net 面试题目
    Linux 最常用150个命令汇总
    .net core 国际化(web通用版)
    vim 命令合集
    解决Mariadb安装时的Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-qenllaxj/mysqlclient/报错
    正则表达式
    python中的JWT
    chapter2.3、react高阶组件,装饰器
  • 原文地址:https://www.cnblogs.com/lancelee98/p/11647662.html
Copyright © 2011-2022 走看看