草庐IT

二叉树的基本操作

熬夜磕代码丶 2023-08-06 原文

个人主页:熬夜磕代码丶
作品专栏: 数据结构与算法
我变秃了,也变强了
给大家介绍一款程序员必备刷题平台——牛客网
点击注册一起刷题收获大厂offer吧

文章目录


一、二叉树的创建

这里我们采用孩子表示法。

 class TreeNode {
        public int val;
        public TreeNode left;//左孩子
        public TreeNode right;//右孩子

        public TreeNode(int val) {
            this.val = val;
        }

    }

二、具体操作

先序遍历

先序遍历的顺序是:根节点-》左子树 -》右子树,这里我们用递归实现。先去判断结点是否为空,如果为空直接返回,不为空,先打印根节点,然后去遍历左子树,然后遍历右子树。

public void perOrder(TreeNode root) {
        //先序遍历
        if(root == null) {
            return;
        }
        System.out.print(root.val+" ");
        perOrder(root.left);
        perOrder(root.right);
    }

中序遍历

先序遍历的顺序是:左子树-》根节点 -》右子树,这里我们用递归实现。先去判断结点是否为空,如果为空直接返回,不为空,先遍历左子树,然后去打印根节点,然后遍历右子树。

public void inOrder(TreeNode root) {
        //中序遍历
        if(root == null) {
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }

后序遍历

先序遍历的顺序是:左子树-》右子树 -》根节点,这里我们用递归实现。先去判断结点是否为空,如果为空直接返回,不为空,先遍历左子树,然后去遍历右子树,然后打印根节点。

public void postOrder(TreeNode root) {
        //后序遍历
        if(root == null) {
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }

层序遍历

层序遍历就是按每一层来遍历二叉树。

我们定义一个队列,首先把二叉树的根节点放入队列

然后我们进行循环,如果队列qu不为空的话定义一个结点cur接受一下qu弹出的结点,如果cur的左子树不为空则入队,右子树不为空入队,打印cur。

void levelOrder(TreeNode root) {
        if(root == null) {
            return;
        }
        Queue<TreeNode> qu = new LinkedList<>();
        qu.offer(root);
        while(!qu.isEmpty()) {
            TreeNode node = qu.poll();
            System.out.print(node.val + " ");
            if(node.left != null) {
                qu.offer(node.left);
            }
            if(node.right != null) {
                qu.offer(node.right);
            }
        }
    }

获取结点个数

这里我们有两种解决方案分别是遍历思路子问题方法
1.遍历:我们定义一个静态成员变量nodeSize,用来记录结点个数,进行先序遍历,每遍历一个结点nodeSize加一。

public static  int nodeSize = 0;
    void size(TreeNode root) {
        if(root == null) {
            return;
        }
        nodeSize++;
        size(root.left);
        size(root.right);
    }

2.子问题方法:我们将一个二叉树分为左子树和右子树组成,每一个二叉树都是由左子树的结点个数+右子树结点个数+1组成。

int size2(TreeNode root) {
        if(root == null) {
            return 0;
        }
        return size2(root.left) + size2(root.right) + 1;
    }

检测值为value的元素是否存在

比如我们现在要判断二叉树中是否存在D这个元素,我们首先对二叉树进行遍历,如果找到了就返回这个结点,否则一直打印知道结点为Null为止。

// 检测值为value的元素是否存在
    TreeNode find(TreeNode root, char val) {
        if(root == null) {
            return null;
        }
        if(root.val == val) {
            return root;
        }
        TreeNode ret1 = find(root.left,val);
        if(ret1 != null) {
            return ret1;
        }
        TreeNode ret2 = find(root.left,val);
        if(ret2 != null) {
            return ret2;
        }
        return null;
    }

获取叶子节点的个数

获取叶子结点这里我们有两种思路:遍历法子问题
1.遍历法:我们去遍历二叉树,定义一个成员变量leafSize用来记录叶子结点,当某一结点的左子树和右子树都为空时,那么这个结点就为叶子节点,leafSize加一。

public static int leafSize = 0;
    void getLeafNodeCount1(TreeNode root) {
        if(root == null) {
            return;
        }
        if(root.left == null && root.right == null) {
            leafSize++;
        }
        getLeafNodeCount1(root.left);
        getLeafNodeCount1(root.right);
    }

2.子问题方法:我们把二叉树可以分为左子树和右子树,二叉树的叶子结点就是左子树的叶子节点加右子树的叶子结点树。

int getLeafNodeCount2(TreeNode root) {
        if(root == null) {
            return 0;
        }
        if(root.left == null && root.right == null) {
            return 1;
        }
        return getLeafNodeCount2(root.left) + getLeafNodeCount2(root.right);
    }

获取第K层节点的个数

二叉树的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推

比如我们现在想获取第三层的元素,那么就是左子树的k-1层加上右子树k-1层的元素之和,直到k等于1时返回1,如果根节点为空或者k<=0返回0.

int getKLevelNodeCount(TreeNode root, int k) {
        if(root == null || k <= 0) {
            return 0;
        }
        if(k == 1) {
            return 1;
        }
        return getKLevelNodeCount(root.left,k-1) + getKLevelNodeCount(root.right,k-1);
    }

获取二叉树的高度

二叉树的高度就是二叉树最深的一条路线,我们这里进行子问题解决,二叉树的高度就是左子树和右子树的最大高度+1就是二叉树的高度
1.代码一:

int getHeight(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int leftHeight = getHeight(root.left);
        int rightHeight = getHeight(root.right);
        return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
    }

2.代码二:

int getHeight(TreeNode root) {
        if(root == null) {
            return 0;
        }
        return getHeight(root.left) > getHeight(root.right) ? getHeight(root.left) + 1 : getHeight(root.right) + 1;
    }

这里的代码一和代码二一样吗?达到的效果是一样的,但是代码二对代码进行了重复计算。


代码一对左子树的高度和右子树的高度进行了保存,而代码二对左子树和右子树进行了重复计算。

判断二叉树是不是完全二叉树

首先我们得知道什么是完全二叉树,什么不是完全二叉树。
比如它就是一个平衡二叉树。

它就不是平衡二叉树

我们采取的同样是层序遍历的思路,定义一个队列,但我们在入队是时,不管左子树右子树是否为空都入队,当某一个cur为空时跳出循环,判断队列中的元素是否有非空的,如果有那么不是平衡二叉树

boolean isCompleteTree(TreeNode root) {
        if(root == null) {
            return true;
        }
        Queue<TreeNode> qu = new LinkedList<>();
        qu.offer(root);
        while(!qu.isEmpty()) {
            TreeNode node = qu.poll();
            if(node != null) {
                qu.offer(node.left);
                qu.offer(node.right);
            } else {
                break;
            }
        }
        if(!qu.isEmpty()) {
            TreeNode node = qu.poll();
            if(node != null) {
                return false;
            }
        }
        return true;
    }

有关二叉树的基本操作的更多相关文章

  1. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  2. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  3. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

  4. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  5. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  6. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  7. ruby - 在 Ruby 中是否有一种惯用的方法来操作 2 个数组? - 2

    a=[3,4,7,8,3]b=[5,3,6,8,3]假设数组长度相同,是否有办法使用each或其他一些惯用方法从两个数组的每个元素中获取结果?不使用计数器?例如获取每个元素的乘积:[15,12,42,64,9](0..a.count-1).eachdo|i|太丑了...ruby1.9.3 最佳答案 使用Array.zip怎么样?:>>a=[3,4,7,8,3]=>[3,4,7,8,3]>>b=[5,3,6,8,3]=>[5,3,6,8,3]>>c=[]=>[]>>a.zip(b)do|i,j|c[[3,5],[4,3],[7,6],

  8. ruby-on-rails - 如何让 Rails View 返回其关联的操作名称? - 2

    我有一个非常简单的Controller来管理我的Rails应用程序中的静态页面:classPagesController我怎样才能让View模板返回它自己的名字,这样我就可以做这样的事情:#pricing.html.erb#-->"Pricing"感谢您的帮助。 最佳答案 4.3RoutingParametersTheparamshashwillalwayscontainthe:controllerand:actionkeys,butyoushouldusethemethodscontroller_nameandaction_nam

  9. ruby-on-rails - Rails 基本 Base64 身份验证 - 2

    我正在尝试复制此GETcurl请求:curl-D--XGET-H"Authorization:BasicdGVzdEB0YXByZXNlYXJjaC5jb206NGMzMTg2Mjg4YWUyM2ZkOTY2MWNiNWRmY2NlMTkzMGU="-H"Content-Type:application/json"http://staging.example.com/api/v1/campaigns在Ruby中,通过电子邮件+apikey生成身份验证:auth="Basic"+Base64::encode64("test@example.com:4c3186288ae23fd9661c

  10. ruby - 在 Ruby 中实现二叉树 - 2

    我一直在尝试在Ruby中实现BinaryTree类,但我得到了stackleveltoodeep错误,尽管我似乎没有在该特定代码段中使用任何递归:1.classBinaryTree2.includeEnumerable3.4.attr_accessor:value5.6.definitialize(value=nil)7.@value=value8.@left=BinaryTree.new#stackleveltoodeephere9.@right=BinaryTree.new#andhere10.end11.12.defempty?13.(self.value==nil)?true:

随机推荐