我正在尝试将名为sigma()
的方法实现到二叉搜索树类中。此方法的作用是返回BST中差分键的总和。我给出的定义如下:
定义1.二叉树中节点的差分密钥 如果节点是,则元素是整数是节点中的元素 root或是节点中元素与其之间的区别 家长。空节点的差异为0.有关,请参见图1 差异二叉树的例证。总和 T的差分键是9,Σ i = 1 n Δ(i),其中Δ(i)表示 节点i和n的差分密钥,树的大小。
该方法应返回树sigma(T)值的总和。所以在这种情况下,sigma(T)将返回10-4-2 + 3 + 5-3 = 9.我理解所有这一切背后的概念并且很容易在纸上完成,但是将它实现到我的代码中就是我的意思我遇到了麻烦。我需要编写一个包装器方法和一个递归的辅助方法来定义sigma()
。
这是我到目前为止编写的BSTree类(sigma()
已经到底):
package bstreedemo;
import java.util.function.Function;
/**
* A binary search tree <br>
* Requires JDK 1.8 for Function
* @param <E> the tree data type
* @since 12/09/2016
* @see BSTreeAPI
*/
public class BSTree<E extends Comparable<E>> implements BSTreeAPI<E>
{
/**
* the root of this tree
*/
private Node root;
/**
* the number of nodes in this tree
*/
private int size;
/**
* A node of a tree stores a data item and references
* to the child nodes to the left and to the right.
*/
private class Node
{
/**
* the data in this node
*/
public E data;
/**
* A reference to the left subtree rooted at this node.
*/
public Node left;
/**
* A reference to the right subtree rooted at this node
*/
public Node right;
}
/**
* Constructs an empty tree
*/
public BSTree()
{
root = null;
size = 0;
}
@Override
public boolean isEmpty()
{
return size == 0;
}
@Override
public void insert(E item)
{
Node newNode = new Node();
newNode.data = item;
if (size == 0)
{
root = newNode;
size++;
}
else
{
Node tmp = root;
while (true)
{
int d = tmp.data.compareTo(item);
if (d == 0)
{ /* Key already exists. (update) */
tmp.data = item;
return;
}
else if (d>0)
{
if (tmp.left == null)
{ /* If the key is less than tmp */
tmp.left = newNode;
size++;
return;
}
else
{ /* continue searching for insertion pt. */
tmp = tmp.left;
}
}
else
{
if (tmp.right == null)
{/* If the key is greater than tmp */
tmp.right = newNode;
size++;
return;
}
else
{ /* continue searching for insertion point*/
tmp = tmp.right;
}
}
}
}
}
@Override
public boolean inTree(E item)
{
return search(item) != null;
}
@Override
public void remove(E item)
{
Node nodeptr = search(item);
if (nodeptr != null)
{
remove(nodeptr);
size--;
}
}
@Override
public void inorderTraverse(Function func)
{
inorderTraverse(root,func);
}
@Override
public E retrieve(E key) throws BSTreeException
{
if (size == 0)
throw new BSTreeException("Non-empty tree expected on retrieve().");
Node nodeptr = search(key);
if (nodeptr == null)
throw new BSTreeException("Existent key expected on retrieve().");
return nodeptr.data;
}
@Override
public int size()
{
return size;
}
/**
* A recursive auxiliary method for the inorderTraver method that
* @param node a reference to a Node object
* @param func a function that is applied to the data in each
* node as the tree is traversed in order.
*/
private void inorderTraverse(Node node, Function func)
{
if (node != null)
{
inorderTraverse(node.left,func);
func.apply(node.data);
inorderTraverse(node.right,func);
}
}
/**
* An auxiliary method that support the remove method
* @param node a reference to a Node object in this tree
*/
private void remove(Node node)
{
E theData;
Node parent, replacement;
parent = findParent(node);
if (node.left != null)
{
if (node.right != null)
{
replacement = node.right;
while (replacement.left != null)
replacement = replacement.left;
theData = replacement.data;
remove(replacement);
node.data = theData;
return;
}
else
replacement = node.left;
}
else
{
if (node.right != null)
replacement = node.right;
else
replacement = null;
}
if (parent==null)
root = replacement;
else if (parent.left == node)
parent.left = replacement;
else
parent.right = replacement;
}
/**
* An auxiliary method that supports the search method
* @param key a data key
* @return a reference to the Node object whose data has the specified key.
*/
private Node search(E key)
{
Node current = root;
while (current != null)
{
int d = current.data.compareTo(key);
if (d == 0)
return current;
else if (d > 0)
current = current.left;
else
current = current.right;
}
return null;
}
/**
* An auxiliary method that gives a Node reference to the parent node of
* the specified node
* @param node a reference to a Node object
* @return a reference to the parent node of the specified node
*/
private Node findParent(Node node)
{
Node tmp = root;
if (tmp == node)
return null;
while(true)
{
assert tmp.data.compareTo(node.data) != 0;
if (tmp.data.compareTo(node.data)>0)
{
/* this assert is not needed but just
in case there is a bug */
assert tmp.left != null;
if (tmp.left == node)
return tmp;
tmp = tmp.left;
}
else
{
assert tmp.right != null;
if (tmp.right == node)
return tmp;
tmp = tmp.right;
}
}
}
/********************* Method Begins Here **********************/
/**
* A wrapper method for a method that computes the
* sum of the differential keys of this binary search tree.
* @return the sum of the differential keys of this tree.
*/
@Override
public int sigma()
{
if (size == 0)
return 0;
if (root.data.getClass() != Integer.class)
throw new IllegalArgumentException("Keys must be integers");
return (Integer)root.data + sigma(root);
}
/**
* An auxiliary method that recursively computes the sum of
* differential keys in the subtrees of the tree rooted at
* the specified key.
* @param subtreeRoot the root of a subtree of this tree
* @return the sum of the differential keys of the left and
* right subtrees
*/
private int sigma(Node subtreeRoot)
{
if(subtreeRoot == null)
return 0;
if(subtreeRoot.left != null)
{
if(subtreeRoot.right != null)
{
return (Integer)subtreeRoot.data + sigma(subtreeRoot.left) + sigma(subtreeRoot.right);
}
else
return (Integer)subtreeRoot.data + sigma(subtreeRoot.left);
}
if(subtreeRoot.right != null)
return sigma(subtreeRoot.right) - (Integer)subtreeRoot.data;
return (Integer)subtreeRoot.data;
}
/********************* Method Ends Here **********************/
/**
* Determines whether this binary tree is perfect
* @return true if the binary tree is perfect, otherwise false
*/
@Override
public boolean isPerfect()
{
}
/**
* A wrapper method that computes the height of this tree
* @return the height of this tree
*/
@Override
public int height()
{
return height(root);
}
/**
* An auxiliary method that recursively computes
* the height of the subtree rooted at the specified node.
* @param node a root of a subtree
* @return the height of this tree
*/
private int height(Node node)
{
if(node == null)
return 0;
return 1 + Math.max(height(node.left), height(node.right));
}
/**
* Determines whether this binary tree is complete.
* @return true if this binary tree is complete, otherwise false
*/
@Override
public boolean isComplete()
{
}
/**
* An auxiliary method that recursively determines whether
* the index of the subtree rooted at the specified node is
* less than the size of this tree.
* @param node a root of a subtree
* @param index the index of this node
* @return
*/
private boolean isComplete(Node node, int index)
{
}
}
wrapper方法返回根节点的数据,将其转换为Integer,添加到在根节点上执行的辅助方法返回的值。
我认为有三种情况需要考虑:
if(subtreeRoot == null)
if(subtreeRoot.left != null && subtreeRoot.right != null) // Parent node has left and right child nodes
if(subtreeRoot.left != null || subtreeRoot.right != null) // Parent node has only left or right child node
这就是我陷入困境的情况,例如2和3.我知道目标是从父节点的值中减去左子和/或右子的值以找到值(s )对于该子树的差分密钥,然后递归执行相同操作的左和/或右剩余子树并将结果相加。但我不知道从哪里开始。我们不允许为项目的方法添加参数/参数,因此(Node subtreeRoot)
是辅助方法允许的唯一参数,而包装器方法不带参数。创建函数&lt;&gt;是否有用简化问题,是我的逻辑缺陷等?任何帮助或进一步的解释都是值得赞赏的,因为我此时有点失落,而我的教授没有任何帮助。
答案 0 :(得分:1)
正如MrMcGreg已经指出的那样,你正在使主逻辑远变得复杂。
由于节点没有与其父节点的链接,因此您的递归函数需要将父节点的值传递给例程。您将获得从此伪代码派生的代码:
int sigma_aux (node root, int parent_val) {
if !node
return 0
else
root_val = root->data
return root_val - parent_val +
sigma_aux(root->left , root_val) +
sigma_aux(root->right, root_val)
那是 it ;只是一个基本案例和一个递归案例。用铅笔和纸跟踪它,直到你理解它为止 - 然后在代码的上下文中实现它。
OP写道:...类似
return (Integer) subtreeRoot.data - (Integer) root.data + sigma(subtreeRoot.left) + sigma(subtreeRoot.right);
?我不明白如何获取父节点的值。一世 认为父节点是传入的子树节点 辅助方法,它的子节点是subtreeRoot.left和 subtreeRoot.right
你控制传递给辅助方法的内容;不要把你的第一个概念作为给定的。这是你感到困惑的地方。简化:顶级 sigma 的唯一真正目的是将树根的数据传递给 sigma_aux ,并执行最顶层的计算以返回到外部世界。
int sigma(node root){ root_val = root-&gt; data;
在此之后,它看起来就像 sigma_aux 。
答案 1 :(得分:1)
你必须是我班上的某个人......无论如何,你必须使用 findParent 方法,因为你没有通过 sigma中的父节点方法
private int sigma(Node subtreeRoot) {
int tot = 0;
if (subtreeRoot == null) {
return 0;
}
if (findParent(subtreeRoot) == null) {
tot = sigma(subtreeRoot.left) + sigma(subtreeRoot.right);
} else{
tot = (Integer) subtreeRoot.data - (Integer) findParent(subtreeRoot).data
+ sigma(subtreeRoot.left) + sigma(subtreeRoot.right);
}
return tot;
}
使用 findParent 方法的if语句是因为该方法将返回null,因为subtreeRoot是树的根,因此它没有父级。然后,当您为左右孩子调用 sigma 方法时,他们将按照else语句进行操作。
我坚持 isPerfect 方法。如果我创建一个aux方法并使用递归,我可以做到,但我们不应该这样做......