Java 计算二叉搜索树中的节点数
我需要创建一个递归方法,将二叉搜索树的根节点作为参数。然后,此递归方法将返回整个二叉搜索树中节点总数的int值 这就是我到目前为止所做的:Java 计算二叉搜索树中的节点数,java,recursion,binary-search-tree,Java,Recursion,Binary Search Tree,我需要创建一个递归方法,将二叉搜索树的根节点作为参数。然后,此递归方法将返回整个二叉搜索树中节点总数的int值 这就是我到目前为止所做的: public class BinarySearchTree<E> extends AbstractSet<E> { protected Entry<E> root; //called by the main method public int nodes() { return nodes(root); }
public class BinarySearchTree<E> extends AbstractSet<E>
{
protected Entry<E> root;
//called by the main method
public int nodes()
{
return nodes(root);
}
//nodes() will count and return the nodes in the binary search tree
private int nodes(Entry<E> current)
{
if(current.element != null)
{
if(current.left == null && current.right == null)
{
if(current.element == root.element)
return 1;
deleteEntry(current);
return 1 + nodes(current.parent);
}
else if(current.left != null && current.right == null)
return nodes(current.left);
else if(current.left == null && current.right != null)
return nodes(current.right);
else if(current.left != null && current.right != null)
return nodes(current.left) + nodes(current.right);
} else return 1;
return 0;
}
所以我按顺序运行搜索,一旦我到达一个没有子节点的节点,我会删除当前节点并返回到父节点并继续。我对上面的方法进行了调试,当程序最终计数并删除根节点左侧和右侧的所有节点并尝试返回1时,程序因NullPointerException()崩溃
这是我的实验室,方法必须是递归的
在这一点上我很迷茫,有人知道我做错了什么吗?在删除
current
后:deleteEntry(current)
,在中使用current.parent
返回1+个节点(current.parent)代码>
可能这就是引发NullPointerException的原因。您有几个问题:
- 在计算节点时删除节点?
nodes()
应该清除树吗
- 您正在处理
root==null
,root=null&left==null&right==null
,根目录=空&左=null&right==null
,等作为单独的案例。他们不是。您有三个案例,它们并不完全是排他性的:
- 如果当前节点不为null,则将一个添加到计数中。(应该总是这样。唯一可能为false的情况是当前节点==
根,我们可以事先检测并避开它。)
- 如果当前节点具有左子节点,请添加左子节点的计数
- 如果当前节点具有正确的子节点,请添加正确子节点的计数
- 你是因为一些不虔诚的原因在树上来回移动。看起来它与删除节点有关
但我认为最重要的是,您没有给予条目足够的自主权
s:P
节点可以计算自己的子节点。相信它
class Entry<E> {
...
int count() {
int result = 1;
if (left != null) result += left.count();
if (right != null) result += right.count();
return result;
}
}
public int nodes() {
return (root == null) ? 0 : root.count();
}
类条目{
...
整数计数(){
int结果=1;
if(left!=null)result+=left.count();
if(right!=null)result+=right.count();
返回结果;
}
}
公共int节点(){
返回值(root==null)?0:root.count();
}
如果您的老师不称职,并且坚持在节点外执行某些节点计数功能,您可以执行与您尝试执行的相同操作:
private int nodes(Entry<E> current) {
int result = 1;
if (current.left) result += nodes(current.left);
if (current.right) result += nodes(current.right);
return result;
}
public int nodes() {
return (root == null) ? 0 : nodes(root);
}
private int节点(当前条目){
int结果=1;
if(current.left)result+=节点(current.left);
if(current.right)result+=节点(current.right);
返回结果;
}
公共int节点(){
返回(root==null)?0:节点(root);
}
但在我看来,那个老师应该被解雇。条目
类是实树BinarySearchTree
实际上只是根目录引用的容器
另外请注意,我一点也不在乎父项。如果我们从根开始计数,每个节点计算它的子节点,子节点计算它们的子节点,等等。。。然后将计算所有节点。这样做太复杂了。面向对象编程的基本思想是相信对象能够完成它们知道答案的任务。所以如果我是父母,我可以算我自己,我让我的孩子算他们自己,等等
private int nodes(Entry<E> current) {
// if it's null, it doesn't exist, return 0
if (current == null) return 0;
// count myself + my left child + my right child
return 1 + nodes(current.left) + nodes(current.right);
}
private int节点(当前条目){
//如果为null,则它不存在,返回0
if(current==null)返回0;
//数一数我自己+我左边的孩子+我右边的孩子
返回1+节点(当前.左)+节点(当前.右);
}
嘿,我为二叉树实现了一个非常干净的计数:
public class Binary<T> where T: IComparable<T>
{
private Node _root;
public int Count => _root.Count;
public void Insert(T item)
{
Node newNode = new Node(item);
if (_root == null)
_root = newNode;
else
{
Node prevNode = _root;
Node treeNode = _root;
while (treeNode != null)
{
prevNode = treeNode;
treeNode = newNode.Item.CompareTo(treeNode.Item) < 1 ? treeNode.Left : treeNode.Right;
}
newNode.Parent = prevNode;
if (newNode.Item.CompareTo(prevNode.Item) < 1)
prevNode.Left = newNode;
else
prevNode.Right = newNode;
}
}
public class Node
{
public T Item;
public Node Parent;
public Node Left;
public Node Right;
public Node(T item, Node parent = null, Node left = null, Node right = null)
{
Item = item;
Parent = parent;
Left = left;
Right = right;
}
public int Count
{
get
{
int count = 1;
count += Left?.Count ?? 0;
count += Right?.Count ?? 0;
return count;
}
}
}
}
公共类二进制文件,其中T:IComparable
{
私有节点_根;
public int Count=>_root.Count;
公共无效插入(T项)
{
节点newNode=新节点(项);
如果(_root==null)
_根=新节点;
其他的
{
节点prevNode=\u根;
节点树节点=_根;
while(treeNode!=null)
{
prevNode=treeNode;
treeNode=newNode.Item.CompareTo(treeNode.Item)<1?treeNode.Left:treeNode.Right;
}
newNode.Parent=prevNode;
if(newNode.Item.CompareTo(prevNode.Item)<1)
prevNode.Left=newNode;
其他的
prevNode.Right=newNode;
}
}
公共类节点
{
公共交通项目;
公共节点父节点;
公共节点左;
公共节点权;
公共节点(T项,节点父节点=null,节点左节点=null,节点右节点=null)
{
项目=项目;
父母=父母;
左=左;
右=右;
}
公共整数计数
{
得到
{
整数计数=1;
计数+=左?计数??0;
计数+=右?计数??0;
返回计数;
}
}
}
}
也许这有助于您理解如何为一个简单的二叉树实现一个带有计数的类
此实现通过树中相应节点中的计数来访问计数
如果您不熟悉.NET 4.6的标记,那么现在让我来解释一下,您还应该对答案进行一些解释。
public int countNodes(Node root){
// empty trees always have zero nodes
if( root == null ){
return 0;
}
// a node with no leafes has exactly one node
// note from editor: this pice of code is a micro optimization
// and not necessary for the function to work correctly!
if( root.left == null && root.right == null ){
return 1;
}
// all other nodes count the nodes from their left and right subtree
// as well as themselves
return countNodes( root.left ) + countNodes( root.right ) + 1;
}
public int countNodes(Node root){
// empty trees always have zero nodes
if( root == null ){
return 0;
}
// a node with no leafes has exactly one node
// note from editor: this pice of code is a micro optimization
// and not necessary for the function to work correctly!
if( root.left == null && root.right == null ){
return 1;
}
// all other nodes count the nodes from their left and right subtree
// as well as themselves
return countNodes( root.left ) + countNodes( root.right ) + 1;
}