java 求二叉树的叶子结点,下面的代码不知道哪里出错了!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 求二叉树的叶子结点,下面的代码不知道哪里出错了!相关的知识,希望对你有一定的参考价值。

package com.overtake;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class BintreeTest
public static void main(String[] args) throws Exception
MyTree myTree = new MyTree();
myTree.root = new BintNode();
myTree.createbintree(myTree.root);
System.out.print("当前树的前序:");
myTree.preorder(myTree.root);
// System.out.println("\n==========");
System.out.println("\n叶子结点个数为:" + myTree.num(myTree.root));



class MyTree
// BintNode bintNode;
BintNode root;
int count = 0;

void createbintree(BintNode myTree) throws Exception
String str;
// myTree = new BintNode();
System.out.println("请输入结点:");
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
str = reader.readLine();
if ("".equals(str.trim()))
myTree = null;
else
myTree.data = str;
myTree.lchild = new BintNode();
createbintree(myTree.lchild);
myTree.rchild = new BintNode();
createbintree(myTree.rchild);





public int num(BintNode root2)
if (root2 == null)
return 0;
else if (root2.lchild == null && root2.rchild == null)
return 1;
else
return (num(root2.lchild) + num(root2.rchild));



void preorder(BintNode r) // /前序
if (r != null)
if (r.lchild != null || r.rchild != null)
System.out.print(r.data + " ");
else if (r.lchild == null || r.rchild == null)
System.out.print("");
else
System.out.print(r.data);

preorder(r.lchild);
preorder(r.rchild);




class BintNode
String data;
BintNode lchild;
BintNode rchild;

我看了一下,知道lz的错误在哪了。
createbintree方法中。以lz的讲的先输入a、再输入三回车,也就是当前只有一个节点a。下面就以楼主的数据来讲一下函数所走流程
1.可是当楼主输入a之后,按完第一个回车
当前取得的数据a,走else分支,接下来就到myTree.data = str;//为节点赋值,假设为父节点1
myTree.lchild = new BintNode();//为myTree建立了左节点
createbintree(myTree.lchild);
//递归调用跳到2
myTree.rchild = new BintNode();//创建右节点
createbintree(myTree.rchild);
//递归调用跳到3
2.输入第二个回车,数据为空,那么走if分支,myTree=null,照理说应该将myTree该节点赋值为空,也就代表没有该节点。
其实这个想法是错误的。在1中,为父节点1分配了左孩子,已经是new出来的对象。不知道lz对函数调用中的形参(也就是函数名所带的参数)的值,是怎么理解。有两种形式的
1)值传递:即使是值传递,在函数体中,改变的也只是一个临时变量的值。并不会影响到实参的值
2)引用传递:对象间的传递,而这传递只是引用关系的传递。就是将该参数指向该类,如果在函数体中设为null,也只是将形参与实际对象间的引用关系给去掉
本程序中,是属于引用传递,在createbintree将myTree=null,也只是断掉myTree与外部对象的关系而已,即父节点1的左孩子间的关系,所以父节点1的左孩子不为null
3.与2同样的解释,也可知道右孩子也不为空。
那么在调用num来计算叶子的个数时候,是不是根结点一开始进来,左右孩子都不为null,所以自然最后一个else。那么往下,lz再计算一下就知道结果为2

建议修改的话:
在createbintree方法中,if ("".equals(str.trim()))为空时,则myTree.data=null
然后在num方法中,计算个数的话,利用myTree.data==null return 0 ; myTree.lchild.data==null && myTree.rchild.data==null return 1 ; else 一样
参考技术A 你的方法是一个递归调用,你这样写要多输入很多的空白字符了,还有假如按输入的结果来看,你输入的值先是填入左子树,接下是左子树的左子树,这样下去,当你输入空字符之后,就递归回来,这时你还有输入 myTree.rchild = new BintNode();
createbintree(myTree.rchild);
这段代码的回调了。
。你输完数字之后多按几下回车它会出结果的(这中间不要输入值否则会增加要输入的回车)。这样你写二叉树有问题了(虽然是一个二叉树了,我想应该违背了你最初的意思了,即使没有违背,那你输入的方式也会很麻烦了)。追问

不才,还是不知道怎么解决
举个简单的例子:
输入一个a后再连续三个回车,就创建了一个只有根的二叉树。
输出的前序是a
但叶子结点输出是2(本来应该是1的)

追答

刚刚我解释了一大段,不过看下面的发现自己错了.你提的问题下面解析清楚了,我就不再重复了,你可以看下面同仁的回答了.

数据结构 二叉树的简单理解和代码实现

前言:本章主要介绍二叉树的链式结构,及其前序、中序、后序遍历操作,还有 二叉树的其它基本操作包括求结点个数、求叶子结点个数、求第K层结点个数、求二叉树深度等。



二叉树的链式结构

链式结构实现如下:

typedef char BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* right;
	struct BinaryTreeNode* left;
}BTNode;

二叉树的遍历方式


前序/中序/后续遍历代码实现

上面已经说到,前序遍历方式为根结点—>左子树—>右子树,我们用下图为例

前序遍历代码:

//二叉树前序遍历
void PreOrder(BTNode* root) {
	if (root == NULL) {
		printf("NULL ");
		return;
	}

	printf("%c ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}

中序遍历代码:

// 二叉树中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL) {
		printf("NULL ");
		return;
	}

	InOrder(root->left);
	printf("%c ", root->data);
	InOrder(root->right);
}

后序遍历代码如下:

// 二叉树后序遍历
void PostOrder(BTNode* root)
{
	if (root == NULL) {
		printf("NULL ");
		return;
	}

	PostOrder(root->left);
	PostOrder(root->right);
	printf("%c ", root->data);
}

二叉树的基本操作

求二叉树结点个数

方法一:用全局遍历

1、全局
int size = 0;//这里不妨思考下能不能直接放入BinaryTreeSize函数内部进行定义
int BinaryTreeSize(BTNode* root)
{
	
	if (root == NULL)
	{
		return;
	}
	else
	{
		++size;
	}

	BinaryTreeSize(root->left);
	BinaryTreeSize(root->right);
}

方法二:局部变量

2、遍历  -- 局部变量
void BinaryTreeSize(BTNode* root, int* psize)
{
	if (root == NULL)
		return;
	else
		++(*psize);

	BinaryTreeSize(root->left, psize);
	BinaryTreeSize(root->right, psize);
}

方法三:

用递归的思想分治,计算二叉树的结点数量,可以认为 数量 = 1 + 左子树数量 + 右子树数量,其中1是当前根结点数量

//3、分治,不再遍历
int BinaryTreeSize(BTNode* root)
{
	return root == NULL ? 0 : 1
		+ BinaryTreeSize(root->left)
		+ BinaryTreeSize(root->right);
}

求二叉树叶子结点个数

按照递归思想,计算二叉树的叶子结点数量,我们可以认为数量等于 = 0 + 左子树叶子结点数量 + 右子树叶子结点数量,0是因为当前根结点有子树,说明根结点不是叶子结点.

//求叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	else if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	else
	{
		return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
	}
}

求二叉树第K层结点个数

核心思路:求当前树的第k层=左子树的第k-1层+右子树的第k-1层

//求第k层节点个数
//核心思路:求当前树的第k层=左子树的第k-1层+右子树的第k-1层
int BinaryTreeLevelKSize(BTNode* root, int K)
{
	if (root == NULL)
	{
		return 0;
	}
	if (K == 1)
	{
		return 1;
	}
	return BinaryTreeLevelKSize(root->left, K- 1) + BinaryTreeLevelKSize(root->right, K - 1);

}

求二叉树的深度/高度

二叉树的高度等于1 + 左右子树高度的最大值.

//二叉树的深度/高度
int BinaryTreeDepth(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	int leftDepth = BinaryTreeDepth(root->left);
	int rightDepth = BinaryTreeDepth(root->right);

	return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}

查找二叉树中值为x的结点

递归分治,先判断当前结点是否是目标,然后查找左子树,再查找右子树.

如果左右子树都没有找到,就返回NULL

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	
	if (root->data == x)
		return root;

	BTNode* retLeft = BinaryTreeFind(root->left, x);
	if (retLeft)
	{
		return retLeft;
	}
	
	BTNode* retRight = BinaryTreeFind(root->right, x);
	if (retRight)
	{
		return retRight;
	}

	return NULL;
}

二叉树源代码

二叉树源代码


数据结构的二叉树内容到此介绍结束了,感谢您的阅读!!!如果内容对你有帮助的话,记得给我三连(点赞、收藏、关注)——做个手有余香的人。

以上是关于java 求二叉树的叶子结点,下面的代码不知道哪里出错了!的主要内容,如果未能解决你的问题,请参考以下文章

java数据结构二叉树查找结点操作,递归调用求详细讲解

数据结构 二叉树的简单理解和代码实现

求二叉树中从根结点到叶子节点的路径

C语言 求二叉树根节点到叶子节点的路径

如何删除一棵普通二叉树的叶子结点?

数据结构算法设计——统计二叉树叶子结点的个数,并输出结果