二叉树系列的代码

6、翻转二叉树:226. 翻转二叉树

分析:

我们直接在原来的树上面修改,先遍历这颗树,然后交换左右子树节点,遍历方式就选前序遍历

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) 
    {
        if (root == NULL) return root;
         swap(root->left,root->right);  //遍历到了根节点
         invertTree(root->left);         // 左
         invertTree(root->right);        // 右 
        return root;
    }
};

8、对称二叉树

先遍历左右子节点,然后比较之后将结果返回到上一层头节点间,后序

class Solution {
public:
    bool compare(TreeNode* left, TreeNode* right) {
        // 首先排除空节点的情况
        if (left == NULL && right != NULL) return false;
        else if (left != NULL && right == NULL) return false;
        else if (left == NULL && right == NULL) return true;
        // 排除了空节点,再排除数值不相同的情况
        else if (left->val != right->val) return false;

        // 此时就是:左右节点都不为空,且数值相同的情况
        // 此时才做递归,做下一层的判断
        bool outside = compare(left->left, right->right);   // 左子树:左、 右子树:右
        bool inside = compare(left->right, right->left);    // 左子树:右、 右子树:左
        bool isSame = outside && inside;                    // 左子树:中、 右子树:中 (逻辑处理)
        return isSame;

    }
    bool isSymmetric(TreeNode* root) {
        if (root == NULL) return true;
        return compare(root->left, root->right);
    }
};

9、树的最大深度

迭代法

1、二叉树的深度,根节点到任意一个节点的距离,中是我们的处理过程,往下一个就加上一,中、左、由前序遍历 

2、二叉树的高度,尾端到任意一个节点的距离,下往上遍历,将结果返回给上一个节点,后序遍历

3、根节点的高度,就是最大深度

 //深度一般是前序遍历,也就是根节点到任意一个节点的距离,
 //最大深度是也是根节点的高度
class Solution {
public:
    int maxDepth(TreeNode* root) {
        return getheight(root);


    }
    int getheight(TreeNode*root){

        if(root == nullptr) return 0;
       
        int ledepth = getheight(root->left);  //左
        int ridepth = getheight(root->right);  //右
        int height =  max(ledepth,ridepth) +1;   //根节点比左右子节点高度加一,该结果会返回给根结点

        return height;

    }

};

层序遍历

分析:这个不就是求层数吗

  • 树的深度:树内所有节点深度的最大值,也就是所有叶子节点深度的最大值,也就是树的层数

  • 树的高度:树内所有节点高度的最大值,也就是根节点的高度,也就是树的层数

class Solution {
public:
    int maxDepth(TreeNode* root) {
        queue<TreeNode*> que;//辅助队列
        int nums = 0;
         if(root != NULL) que.push(root);//头节点入栈
            
        while(!que.empty())
        {
            int size = que.size();//记下每层元素个数
            nums++;
            
            for(int i = 0 ; i < size; i++)
            {
                TreeNode* node = que.front();//获取栈顶指针
                que.pop();//父亲进去
                if(node ->left) que.push(node ->left);
                if(node ->right) que.push(node ->right);     
            }
        }
       return nums;
    }

};

10、最小深度

最小深度是从根节点到最近叶子节点的最短路径上的节点数量

叶子节点是没有子节点的节点

求最小深度与求高度的意思差不多,我们使用后序遍历简单点

//求深度一般是前序,但是比较麻烦,我们使用后序通过高度求深度逻辑是一样的
class Solution {
public:
    int minDepth(TreeNode* root) {
        return Getheight(root);


    }
    int Getheight(TreeNode* root)
    {
        if(root == NULL) return 0;  //终止条件

        int leftheight =  Getheight(root ->left);  //左
        int rightheight = Getheight(root ->right); //右

        //一个节点为空,一个节点不为空,根节点的高度就是不为空的节点的高度 +1
        
        //下面是访问根节点也就中,一般都是通过return 访问到从子节点跳到根结点
        if( root -> left == NULL && root ->right != NULL) return  rightheight +1;
        else if( root -> left != NULL && root ->right == NULL) return  leftheight +1;
        else//当节点都不为空的时候
          {
              return min(leftheight,rightheight) +1;
          }
    
        



    }
};

11、完全二叉树的节点个数

普通二叉树

直接使用后序遍历,先遍历左右节点的节点数,然后将统计结过上传到中节点

class Solution {
public:
    int countNodes(TreeNode* root) {
        return Getnums(root);
        

    }
    int Getnums(TreeNode* root){
        if(root == NULL) return 0;//终止条件

        int leftnums = Getnums(root ->left); //左
        int rightnums = Getnums(root ->right);//右

       int result = leftnums + rightnums +1;// 中 ,统计的数据传给中节点 +1,是加上了根及节点的
        return result;

    }
};

12、平衡二叉树

题目解析:

任意一个节点的左右子树的高度度差值不大于1

1、高度是距离最尾端叶子节点的距离(后序遍历,会向上返回结果)

使用递归的方法

后序遍历,先遍历左右节点是否满,然后将本层左右节点比较看是否满足条件

不满足条件的节点我们赋值-1,满足条件的我们会将高度赋值给他

110. 平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

使用后序遍历先判断子节点然后返回到中节点

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

//使用递归的方法
class Solution {
public:
   
    int Getheight(TreeNode* root){

        if(root == NULL) return 0;//终止条件

        int leftheight =  Getheight(root ->left);  //左
        if(leftheight == -1) return -1;//将-1返回给左节点
        
         int rightheight =  Getheight(root ->right); //右
        if(rightheight == -1) return -1;//将-1返回给右节点
        
        //中
        int res;
        if(abs(leftheight  -  rightheight) > 1) //比较这一层的左右节点的值,讲结果返回给上一层
            res = -1;
        else
             res = max(leftheight,rightheight) +1;//没有赋值的int,默认都是0
        return res;
    }
    bool isBalanced(TreeNode* root) {

       return Getheight(root) == -1 ? false:true;       
    }
    
};

15、左叶子之和

分析:

使用后序遍历,将我们结果上传

 难点在怎么判断是左子叶,该结点是上一个节点的左结点,自己的左右节点都是空

//使用后序遍历,将我们结果上传
 //难点在怎么判断是左子叶,该结点是上一个节点的左结点,自己的左右节点都是空

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        return Getsum(root);

    }
    int Getsum(TreeNode* root)
    {
        if(root == NULL) return 0;//终止条件

       int leftnums = Getsum(root ->left); //左
          

       if(root ->left != NULL && root ->left->left ==NULL && root ->left ->right == NULL)
           leftnums  =root ->left ->val;
             
        int rightnums = Getsum(root ->right);//右

        return leftnums + rightnums; //中
    }
};

16、找树左下角的值

在树的最后一行找到最左边的值。

首先要是最后一行,然后是最左边的值

使用层序遍历很简单,每一层第一个就是最左边的

迭代法

//使用层序遍历简单,在每一层中左边都是先遍历的,把每一层的第一个第一都存放在一个变量中,最后剩下来的就是左下角的
class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
     queue<TreeNode*>que;
     if(root == NULL)  return 0;
     else que.push(root);//第一层入栈
     int result = 0;
     while(!que.empty())
     {
           int size = que.size();
           for(int i = 0; i < size;i++)
           {
               TreeNode* node = que.front();
               que.pop();
               if(i == 0) result = node ->val;//每层最左边的一个元素
               if(node->left) que.push(node ->left);
               if(node->right) que.push(node ->right);
           }

     }
        
    return result;
    }
};

19、最大二叉树

选择一个最大值作为根节点,然后从左边选择一个最大作为左子树节点,从右边选择最大构造右子树,然后一直循环下去,我们数组一直在变化

左子树区间 nums.begin(),nums.begin()+maxvalueindex )//左闭右开

右子树区间 nums.begin() + maxvalueindex +1,nums.end()

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        TreeNode* node = new TreeNode(0);
        if(nums.size() == 1)  //当将数组中的最后一个值赋给了叶子节点就返回上一层
        {
            node ->val = nums[0];
            return node;
        }
        //找到数组中的最大的值和对应的下标
        int maxValue = 0;
        int maxValueIndex = 0;
        for(int i = 0; i < nums.size();i++){
            if(nums[i] > maxValue){
                maxValue = nums[i];
                maxValueIndex = i;
            }
        }
        node ->val = maxValue;//中
        //根据最大值来构造左子树区间
        if(maxValueIndex > 0){
            vector<int> newVec(nums.begin(),nums.begin()+maxValueIndex);//重新构造左子树区间,左开右闭
            node ->left = constructMaximumBinaryTree(newVec);//左
        }
      if(maxValueIndex < nums.size()-1){
            vector<int> newVec(nums.begin()+maxValueIndex +1,nums.end());//重新构造右子树区间,左开右闭
            node ->right = constructMaximumBinaryTree(newVec);//右
        }
        return node;//返回结果 
    }
};

21、合并二叉树

两个二叉树都有的节点就将二个数值相加,不然就补充进去作为新节点

疑问,我们是把以7为根节点的子树返回到上一层

 

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == NULL) return t2;//终止条件,在我们发现有一方为空的时候就往上退
        if (t2 == NULL) return t1;
        // 重新定义新的节点,不修改原有两个树的结构
        TreeNode* root = new TreeNode(0);
        root->val = t1->val + t2->val;   //中
        root->left = mergeTrees(t1->left, t2->left);//左
        root->right = mergeTrees(t1->right, t2->right);//右
        return root;
    }
};

22、二叉搜索树中的搜索

左子树节点比根节点小,右子树节点比根节点大

二叉搜索树是可以有序的,在中序排列的情况下就是递增的

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == NULL) return t2;//终止条件,在我们发现有一方为空的时候就往上退
        if (t2 == NULL) return t1;
        // 重新定义新的节点,不修改原有两个树的结构
        TreeNode* root = new TreeNode(0);
        root->val = t1->val + t2->val;   //中
        root->left = mergeTrees(t1->left, t2->left);//左
        root->right = mergeTrees(t1->right, t2->right);//右
        return root;
    }
};

23、验证二叉搜索树

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。
  • 中序为什么是越来越大,因为中序节点赋值是从底到顶实现赋值的,

 

不能只是单纯比较左节点小于中间节点,右边节点大于中间节点就完事了

 

我们要直接将每个节点的根存放在一个变量max中,每递归一次就会替换一次,但是现在只有下一个节点大于上一个才可以换,这样上面的根节点必须都要大于上一个根节点

class Solution {
public:
  TreeNode* pre = NULL;//用来记录前一个节点
    bool isValidBST(TreeNode* root) {
      if(root ==NULL ) return true;//终止条件
      bool leftvalue = isValidBST(root ->left);
      if(pre != NULL && pre ->val >= root ->val) //我们这个赋值是自下而上的,所以后面是越来越大
      {
          return false;//跳上一层
      }
      pre = root;//结点更新
      bool rightvalue = isValidBST(root ->right);

      return  leftvalue && rightvalue;
    }
};

24、求二叉搜索树的最小绝对差值

class Solution {
private:
int result = INT_MAX;//存放绝对差
TreeNode* pre = NULL;
void traversal(TreeNode* cur) {
    if (cur == NULL) return;//终止条件
    traversal(cur->left);   // 左
    if (pre != NULL){       // 中
        result = min(result, cur->val - pre->val);
    }
    pre = cur; // pre指针移动到下一个中点
    traversal(cur->right);  // 右
}
public:
    int getMinimumDifference(TreeNode* root) {
        traversal(root);
        return result;
    }
};

25、二叉搜索树中的众数

众数:出现频率最高的数

众数可以有多个

因为中序遍历的话中节点处理节点顺序就是按照从小到大,一样大小的数字都在附近

我们使用中序这样遍历就是按顺序的, pre指针指向上一个根节点,比较相邻根节点是否相同要是相同就count加一,使用一个变量存放count达到的最大值,要是达到最大值就这个root->val 存放到一个容器中,要是count超过了最大值就情况容器,然后将值插入容器中

class Solution {
public:
        int maxCount = 0;//最大频率
        int count = 0;   //统计频率
        TreeNode* pre = NULL;
        vector<int> result;//存放结果

    void searchBST(TreeNode* cur){
            if(cur == NULL) return;
            searchBST(cur ->left);//左
            //中
            if(pre  == NULL) count = 1;//第一个节点
            else if (pre ->val == cur ->val)//第二个节点与第一个节点相同
              count ++;
            else//节点与前一个不同
                 count = 1;//计数初始化
                

            pre = cur;//pre指向当前节点,更新pre指针指向

            if(count == maxCount)//如果和最大值相同,就放进result中
                result.push_back(cur ->val);
            if(count > maxCount)//计数大于最大值频率
            {
              maxCount = count; //更新最大频率
              result.clear();//清空reslut容器
              result.push_back(cur->val);
            }
            
            searchBST(cur ->right);
            return;
            
    }

    vector<int> findMode(TreeNode* root) {
        count = 0;
        maxCount = 0;
        TreeNode* pre = NULL;//记录前一个不同值的节点
        result.clear();
        searchBST(root);
        return result;
        

    }
};

26、二叉树最近的公共祖先

从后往上处理,两个汇聚到一个节点,就是公共祖先,故而使用后序遍历

root 遍历到目标节点就返回,最后中节点做处理,只有左右都找到才返回root,不然只返回我们找到的然后继续找,左右的那个root数据肯定是最后出现会覆盖left,right

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
         
        if(root == q || root == p || root == NULL) return root;//遍历到目标或者空就返回,寻找祖先
        TreeNode* left = lowestCommonAncestor(root ->left,p,q);//左
        TreeNode* right = lowestCommonAncestor(root->right,p,q);//右
        //中,处理逻辑
        if(left != NULL && right != NULL) return root;//左右子节点都找到目标,将根节点返回

        if(left != NULL && right == NULL) return left;//z只有左子节点找到,将左返回
        else if(left == NULL && right != NULL) return right;//只有右子节点找到,将右返回
        else     
             return NULL;
    }
};

28、二叉搜索树的最近公共祖先

从后往上处理,两个汇聚到一个节点,就是公共祖先,故而使用后序遍历

只要发现一个根节点在这两个之间,就说明是最近公共祖先

//我们二叉搜索树比较特殊,直接前序就可以
class Solution {
public:
     TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q)
     {
         if(cur == NULL) return cur;//遍历到底就返回

         //  中不需要什么操作,只要等return 返回结果就好
         //这个if可以直接确定搜索方向,都不需要要什么根、左、右
         if(cur->val > p->val && cur ->val > q->val)//目标在根节点左子树
         {
             TreeNode* left = traversal(cur->left,p,q);
             if(left != NULL) return left;//找到最近公共祖先
         }

         if(cur->val < p->val && cur ->val < q->val)//目标在根节点右子树
         {
             TreeNode* right = traversal(cur->right,p,q);
             if(right != NULL) return right;
         }

         return cur;//代表找到
     }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
      return traversal(root,p,q);
        
    }
};

29、二叉搜索树中的插入操作

位置都在叶子节点上

class Solution {
public:
    TreeNode* parent;
    void traversal (TreeNode* cur,int val){
        
       if(cur == NULL)//找到空节点
       {
           TreeNode* node = new TreeNode(val);
           if(val > parent ->val ) parent->right = node;
           else
              parent->left = node;
           return;//返回上一级
                  
       }
       parent = cur;//中
       if(cur ->val >val)  traversal(cur ->left,val);//左
       if(cur ->val < val) traversal(cur ->right,val);//右
    }
    TreeNode* insertIntoBST(TreeNode* cur, int val) {
      //当实空树,需要我们定义一下parent节点
       parent = new TreeNode(0);
       //当二叉树是空树的时候,直接创建一个节点就可以
        if (cur == NULL) {
            cur = new TreeNode(val);
        }
      traversal(cur,val);
      return cur;
    
    }
};

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树是一种常见的数据结构,它由一个根节点和一系列的左右子节点组成。下面是一个使用C语言实现二叉树操作的代码示例: ```c #include <stdio.h> #include <stdlib.h> // 定义二叉树节点结构体 typedef struct TreeNode { int value; struct TreeNode* left; struct TreeNode* right; } TreeNode; // 创建新节点 TreeNode* createNode(int value) { TreeNode* newNode = malloc(sizeof(TreeNode)); newNode->value = value; newNode->left = NULL; newNode->right = NULL; return newNode; } // 插入节点 void insert(TreeNode** root, int value) { if (*root == NULL) { *root = createNode(value); } else { if (value < (*root)->value) { insert(&((*root)->left), value); } else { insert(&((*root)->right), value); } } } // 删除节点 TreeNode* delete(TreeNode* root, int value) { if (root == NULL) { return root; } if (value < root->value) { root->left = delete(root->left, value); } else if (value > root->value) { root->right = delete(root->right, value); } else { if (root->left == NULL) { TreeNode* temp = root->right; free(root); return temp; } else if (root->right == NULL) { TreeNode* temp = root->left; free(root); return temp; } TreeNode* minNode = root->right; while (minNode->left != NULL) { minNode = minNode->left; } root->value = minNode->value; root->right = delete(root->right, minNode->value); } return root; } // 先序遍历 void preOrder(TreeNode* root) { if (root != NULL) { printf("%d ", root->value); preOrder(root->left); preOrder(root->right); } } // 测试代码 int main() { TreeNode* root = NULL; insert(&root, 5); insert(&root, 3); insert(&root, 7); insert(&root, 2); insert(&root, 4); printf("先序遍历结果:"); preOrder(root); printf("\n"); root = delete(root, 3); printf("删除节点3后的先序遍历结果:"); preOrder(root); printf("\n"); return 0; } ``` 这段代码实现了二叉树的插入、删除和先序遍历操作。其中,`TreeNode`结构体定义了二叉树的节点,`createNode`函数用于创建新的节点,`insert`函数用于插入节点,`delete`函数用于删除节点,`preOrder`函数用于进行先序遍历。在测试代码中,创建了一个二叉树并对其进行先序遍历操作,并删除了节点3后再进行遍历。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值