Java 在二叉搜索树中查找重复项的策略
我有一个BST,它有重复的条目。我正在试图找到重复的条目。现在很明显,我可以编写一个穿越整个树的哑算法,这很简单 然而,我想写一个更有效的。以下是我到目前为止所做的/思考的: 假设下面的树Java 在二叉搜索树中查找重复项的策略,java,algorithm,binary-tree,Java,Algorithm,Binary Tree,我有一个BST,它有重复的条目。我正在试图找到重复的条目。现在很明显,我可以编写一个穿越整个树的哑算法,这很简单 然而,我想写一个更有效的。以下是我到目前为止所做的/思考的: 假设下面的树 10 / \ 5 15 /\ / \ 2 8 10 16 \ \ 8 12 如果我想找到所有的8,我将首先在10的左子树上找到8。若要查找重复节点,若它并没有右子节点,那个么它将是第一个父节点的右子树上最左侧的
10
/ \
5 15
/\ / \
2 8 10 16
\ \
8 12
如果我想找到所有的8,我将首先在10的左子树上找到8。若要查找重复节点,若它并没有右子节点,那个么它将是第一个父节点的右子树上最左侧的节点,该节点大于该节点(8)?如果它确实有一个右子节点,那么它可以位于其右子树的最左侧节点中,也可以位于其左子树的最右侧节点中
这些都是可以通过一系列循环和if语句实现的情况吗
如果不是,有什么更好的方法?有人能帮忙吗
谢谢
编辑:
实际上我刚刚意识到它不可能是“最左边的节点”或“最右边的节点”。这将查找下一个最高值或上一个最低值的节点。它以前会是一个节点吗
编辑2:
修复了我的BST示例。它遵循以下插入方法:
if (node == null)
return new NodeBST<Value>(name, value);
if (node.key().compareTo(name) > 0)
node.setLeft(insert(node.left(), name, value));
else
node.setRight(insert(node.right(), name, value));
if(节点==null)
返回新的NodeBST(名称、值);
如果(node.key().compareTo(name)>0)
setLeft(插入(node.left(),名称,值));
其他的
setRight(插入(node.right(),名称,值));
这意味着副本将添加到副本的右侧。。对吗?您显示的树假设(好吧,至少我假设…;-)小于左边的值,大于右边的值,对吗
因此,有两件事你应该考虑:
递归算法可以快速解决这个问题。您不必在整个树上递归,因为您可以使用BST的结构来查找所需的值 你所画的并不是严格意义上的BST,我可能错了,但我相信这是非常错误的——左边树中的所有数字都应该小于10,反之亦然
此实现使用递归方法并返回重复项数组
public class TreeNode<E> {
public int data;
public TreeNode left;
public TreeNode right;
}
public Integer[] findDuplicate(TreeNode tree) {
Map<Integer, Integer> entries = new HashMap<>();
List<Integer> duplicates = new LinkedList<>();
return (Integer[]) findDuplicate(tree, entries, duplicates);
}
private Integer[] findDuplicate(TreeNode tree, Map entries, List duplicates) {
if (tree == null)
return (Integer[]) duplicates.toArray(new Integer[] {});
if (entries.containsKey(tree.data))
duplicates.add(tree.data);
else
entries.put((int) tree.data, 1);
findDuplicate(tree.left, entries, duplicates);
findDuplicate(tree.right, entries, duplicates);
return (Integer[]) duplicates.toArray(new Integer[] {});
}
公共类树节点{
公共int数据;
公共树节点左;
公共树节点权;
}
公共整数[]findDuplicate(TreeNode树){
Map entries=newhashmap();
列表重复项=新建LinkedList();
返回(整数[])findDuplicate(树、条目、副本);
}
私有整数[]findDuplicate(树节点树、映射项、列表副本){
if(tree==null)
返回(整数[])重复项。toArray(新整数[]{});
if(entries.containsKey(tree.data))
添加(树数据);
其他的
entries.put((int)tree.data,1);
查找副本(tree.left、条目、副本);
查找副本(tree.right、条目、副本);
返回(整数[])重复项。toArray(新整数[]{});
}
你事先知道你要找的是什么数字吗?这不符合BST的目的吗?这不是一个合适的BST。根10的右分支上不能有8。@lynks是的-你得到了要删除的数字。@John Kugelman哦,没错!让我来解决这个问题。对不起,是的,是的,我为我的错误道歉。请参见编辑2。我的插入将它们链接到彼此的右侧。因此,当我找到一个副本时,只需通过它的正确子级/子级来查看所有副本?当然。此外,为了简洁和性能,如果您希望有大量重复项,那么从第一个对象扩展所有类似值对象的链接列表可能是一个好主意。如果真的有大量重复项,可以为包含重复项的叶启动哈希表。。。所有这些都取决于您试图解决的特定问题!对不起,我知道。我犯了一个错误,请参阅修订版2。Thanks我相信在第2步中,它应该是RH分支,因为根据我的插入(如上面的编辑2所示),重复项被插入到节点的右侧子节点。对吗?@Nayefc当你第一次到达(2)时,你可能不知道所有的副本都是右边的。这取决于你如何编写搜索代码。哦,是的,我知道。我只是说我的插入方法将重复项放在节点的右侧。(请参见上述代码+图表)。因此,这不会使步骤2变成:检查右侧分支,而不是左侧分支?@Nayefc,这不会改变任何东西。当你搜索时,你要么在按键相等的情况下继续向左,要么在第一次匹配时停止。如果是后者,则重复项可能在两侧。哦,你给出了整个搜索算法。知道了。。。谢谢