求二叉树中第K层结点的个数

简介:

一,问题描述

构建一棵二叉树(不一定是二叉查找树),求出该二叉树中第K层中的结点个数(根结点为第0层)

 

二,二叉树的构建

定义一个BinaryTree类来表示二叉树,二叉树BinaryTree 又是由各个结点组成的,因此需要定义一个结点类BinaryNode,BinaryNode作为BinaryTree的内部类。

此外,在BinaryTree中需要一定一个BinaryNode属性来表示树的根结点。

复制代码
 1 public class BinaryTree<T extends Comparable<? super T>> {
 2     
 3     private static class BinaryNode<T>{
 4         T element;
 5         BinaryNode<T> left;
 6         BinaryNode<T> right;
 7         
 8         public BinaryNode(T element) {
 9             this.element = element;
10             left = right = null;
11         }
12     
13         public BinaryNode(T element, BinaryNode<T> left, BinaryNode<T> right){
14             this.element = element;
15             this.left = left;
16             this.right = right;
17         }
18     }
19     
20     private BinaryNode<T> root;
21 
22 //other code.....
复制代码

第一行是二叉树类的定义,第三行是结点类的定义,第20行是二叉树根的定义。

 

三,求解第K层结点个数的算法实现

感觉对二叉树中的许多操作都可以用递归来实现。因此,二叉树是理解递归一个好实例。比如,二叉树的操作之统计二叉树中节点的个数二叉树的先序遍历和后序遍历的应用--输出文件和统计目录大小

求第K层结点的个数也可以用递归来实现:

①若二叉树为空或者K小于0,返回0

②若K等于0,第0层就是树根,根只有一个,返回1

③若K大于0,返回左子树中第K-1层结点个数 加上 右子树中第K-1层结点的个数

因为,第K层结点,相对于根的左子树 和 右子树 而言,就是第K-1层结点

 

其实,这是有改进的地方:对于K<0的情形,准确地说:它只是一个非法输入,而不是递归的结束条件(基准条件)。可以看出,①不要把非法输入与递归的基准条件混淆,②把非法输入的判断放到递归中判断的开销是很大的。因为每进行一次递归就需要进行一次非法输入判断。而如果在开始就把非法输入过滤掉,在递归过程中就不会存在每一次递归就判断一次非法输入了。

递归的基准条件只有两个:

1) k==0 当递归到K==0时,说明:第K层是有结点的

2) root==null  当递归到root==null时,说明:第K层没有结点

因此,可以进一步将代码改进如下:这样,不需要在每次递归的过程中还可能附加一次 k<0 的判断

复制代码
 1     /**
 2      * 
 3      * @param k
 4      * @return 二叉树中第K层结点的个数(根位于第0层)
 5      */
 6     public int k_nodes(int k){
 7         if(k < 0)
 8             return 0;
 9         return k_nodes(root, k);
10     }
11     private int k_nodes(BinaryNode<T> root, int k){
12         if(root == null)
13             return 0;
14         if(k == 0)
15             return 1;//根结点
16         else
17             return k_nodes(root.left, k-1) + k_nodes(root.right, k-1);
18     }
复制代码

 

可参考:按层打印二叉树--每行打印一层 来测试每一层是否有正确的结点个数。

四,代码实现

复制代码
 1 public class BinaryTree<T extends Comparable<? super T>> {
 2     
 3     private static class BinaryNode<T>{
 4         T element;
 5         BinaryNode<T> left;
 6         BinaryNode<T> right;
 7         
 8         public BinaryNode(T element) {
 9             this.element = element;
10             left = right = null;
11         }
12     }
13     
14     private BinaryNode<T> root;
15     
16     /**
17      * 向二叉树中插入一个元素
18      * @param element
19      */
20     public void insert(T element){
21         root = insert(root, element);
22     }
23     private BinaryNode<T> insert(BinaryNode<T> root, T element){
24         if(root == null)
25             return new BinaryNode<T>(element);
26         int r = (int)(2*Math.random());
27         //随机地将元素插入到左子树 或者 右子树中
28         if(r==0)
29             root.left = insert(root.left, element);
30         else
31             root.right = insert(root.right, element);
32         return root;
33     }
34     
35     /**
36      * 
37      * @param k
38      * @return 二叉树中第K层结点的个数(根位于第0层)
39      */
40     public int k_nodes(int k){
41         return k_nodes(root, k);
42     }
43     private int k_nodes(BinaryNode<T> root, int k){
44         if(root == null || k < 0)
45             return 0;
46         if(k == 0)
47             return 1;//根结点
48         else
49             return k_nodes(root.left, k-1) + k_nodes(root.right, k-1);
50     }
51     
52     public static void main(String[] args) {
53         BinaryTree<Integer> tree = new BinaryTree<>();
54         
55         int[] ele = C2_2_8.algorithm1(4);//构造一个随机数组,数组元素的范围为[1,4]
56         for (int i = 0; i < ele.length; i++) {
57             tree.insert(ele[i]);
58         }
59         
60         int k_nodes = tree.k_nodes(2);//第二层
61         int k_nodes2 = tree.k_nodes(-1);//第-1层
62         int k_nodes3 = tree.k_nodes(0);
63         int k_nodes4 = tree.k_nodes(1);
64         int k_nodes5 = tree.k_nodes(4);//若超过了树的高度,结果为0
65         System.out.println(k_nodes);
66         System.out.println(k_nodes2);
67         System.out.println(k_nodes3);
68         System.out.println(k_nodes4);
69         System.out.println(k_nodes5);
70     }
71 }
复制代码

 

关于 C2_2_8类,参考:随机序列生成算法---生成前N个整数的一组随机序列

 

五,参考资料

http://blog.csdn.net/luckyxiaoqiang/article/details/7518888


本文转自hapjin博客园博客,原文链接:http://www.cnblogs.com/hapjin/p/5505988.html,如需转载请自行联系原作者

相关文章
|
4月前
|
存储 分布式计算 安全
阿里云服务器ECS实例选型参考:场景适配、应用推荐
选择阿里云服务器ECS实例之前,需要结合性能、价格、工作负载等因素,做出性价比与稳定性最优的决策。对于很多新手用户来说,在初次购买阿里云服务器的时候,面对众多实例规格往往不知道如何选择,因为云服务器实例规格不同,价格也不一样,性能表现更是千差万别。因此,在购买阿里云服务器ECS实例之前,需要结合性能、价格、工作负载等因素,做出性价比与稳定性最优的决策。本文将通过一些常见的选型场景推荐,为大家详细介绍阿里云服务器实例选型的最佳实践,便于大家在选择云服务器实例规格时做个参考。
|
2月前
|
存储 弹性计算
阿里云服务器一小时收费价格,不同ECS是实例按量付费1小时费用整理
阿里云ECS云服务器按小时计费,价格根据实例类型和配置不同而异。例如经济型e实例2核2G配置0.094元/小时,通用算力型u1实例2核4G配置0.351元/小时,计算型c9i实例2核4G配置0.3873元/小时,4核8G配置0.7746元/小时。不同规格实例价格差异明显,具体以官网信息为准。
|
11月前
|
缓存 搜索推荐 索引
「Mac畅玩鸿蒙与硬件12」鸿蒙UI组件篇2 - Image组件的使用
在鸿蒙应用开发中,Image 组件用于加载和显示图片资源,并提供多种属性来控制图片的显示效果和适配方式。本篇将带你学习如何在鸿蒙应用中加载本地和远程图片、设置图片样式以及实现简单的图片轮播功能。
626 7
「Mac畅玩鸿蒙与硬件12」鸿蒙UI组件篇2 - Image组件的使用
|
数据采集 Web App开发 API
虾皮(Shopee)商品详情数据接口详解
虾皮(Shopee)是东南亚与台湾领先的电商市场,为买卖双方搭建桥梁。本文介绍如何利用网页爬虫技术获取商品详情数据,适用于无API访问权限的情况。通过Python的`requests`和`beautifulsoup4`库,可从网页中提取信息。首先需安装上述库,然后使用示例代码发送HTTP请求并解析HTML。注意遵守虾皮的服务条款,应对可能的动态内容和反爬虫措施。对于API需求,建议查阅官方文档。
476 3
|
8月前
|
安全 NoSQL MongoDB
XJ-Survey:这个让滴滴日均处理1.2亿次问卷请求的开源系统,今天终于公开了它的架构密码!
嗨,大家好,我是小华同学。今天为大家介绍一款由滴滴开源的高效调研系统——XJ-Survey。它功能强大,支持多类型数据采集、智能逻辑编排、精细权限管理和数据在线分析,适用于问卷、考试、测评等场景。采用 Vue3、NestJS 等先进技术栈,确保高性能与安全性。无论是企业还是个人,XJ-Survey 都是你不可错过的神器!项目地址:[https://github.com/didi/xiaoju-survey](https://github.com/didi/xiaoju-survey)
267 15
|
8月前
|
存储 搜索推荐 API
淘宝拍立淘按图搜索API接口系列概述
淘宝拍立淘按图搜索API接口允许用户通过上传图片或拍摄实物来搜索相似或相同的商品。这一功能主要依赖于图像识别技术,系统会对上传的图片进行分析和处理,提取出商品的特征信息,并在淘宝的商品数据库中进行匹配搜索,最终返回与上传图片相似或相同的商品列表。
通义灵码1岁啦:灵码编码搭子
我是一位软件开发工程师,使用通义灵码的个人版 @workspace 和 @terminal 功能,快速上手新项目并高效实现需求。相比以前,项目熟悉和需求实现效率提升了约30%,特别是在代码理解和编写方面。通义灵码的代码智能分析、注释补全、编译错误建议等功能大幅减少了手动调试和重复工作,使开发流程更加顺畅和高效。
通义灵码1岁啦:灵码编码搭子
|
监控 安全 Java
Java中的权限管理与访问控制策略
Java中的权限管理与访问控制策略
|
算法
【数据结构与算法】二叉树的深度,节点数,第k层的节点数,遍历,二叉树叶节点的个数
【数据结构与算法】二叉树的深度,节点数,第k层的节点数,遍历,二叉树叶节点的个数
476 0