我正在尝试用Java编写一个平衡二叉树的方法,如下所述:
...写一个inorder遍历树 到一个数组,然后使用递归方法(很像二进制搜索)插入数组的中间元素作为根,然后构建平衡的左右子树。
然而,我对如何一起做这件事感到难过。到目前为止,我尝试了各种方法,但没有任何效果。
我还有一个inOrder迭代器,它返回树中所有元素的ArrayList,这样就可以了。
这是我目前正在建立的:
public void rebalance()
{
Iterator<T> it = iteratorInOrder();
List<T> list = new ArrayList<>();
while (it.hasNext())
{
list.add(it.next());
}
balanceRecursive( );
}
private void balanceRecursive( )
{
//something here
}
然后我只是在add / remove元素方法的末尾有这个:
if ((getHeight() - getMinHeight()) > 5)
rebalance();
那么,我怎么能这样呢?
答案 0 :(得分:0)
在平衡树中,右侧和左侧子树的大小最多相差1个元素。给定一个排序数组 - 由您的inorder-traversal生成 - 这变得非常简单。基本思想是构建一个实际的树,它等于二进制搜索隐式遍历的树。从根数组的中间元素开始,中间左边的子数组的中间元素成为左子元素,右子元素的相同模式。使用数组的左半部分相应地将左子项作为根构建子树,对于右子树也是如此。
//lower and upper are the INCLUSIVE bounds of the sublist, from which the tree should be built
Node<T> buildRecursively(int lower , int upper , List<T> elements){
//no more nodes can be produced on this path
if(lower > upper)
return null;
//build node from the middle-element of the elements
int middle = (lower + upper) / 2;
Node<T> result = new Node<>(elements.get(middle));
//build left and right child for the according pieces of the array/list
result.setLeftChild(buildRecursively(lower , middle - 1 , elements);
result.setRightChild(buildRecursively(middle + 1 , upper , elements);
return result;
}
//build entire tree:
Node<T> root = buildRecursively(0 , elements.size() - 1 , elements);
使用实际数组时,它将如下所示:
sorted ascending--------->
4
2 6
1 3 5 7
indices: 0 1 2 3 4 5 6
答案 1 :(得分:0)
答案 2 :(得分:0)
通过按顺序遍历List
后,这变得相对简单。 sublist
操作意味着您甚至不需要传递索引:
Node<T> buildBalancedTree(List<T> values) {
if (values.isEmpty()) {
return Node.NULL;
} else {
int middle = values.size() / 2;
Node node = new Node(values.get(middle));
node.setLeft(buildBalancedTree(values.subList(0, middle)));
node.setRight(buildBalancedTree(values.subList(middle + 1, values.size())));
return node;
}
}
我假设你有一个Node.NULL
代表空子树而不是'null',因为你应该: - )
所以你的重新平衡方法看起来像是:
root = buildBalancedTree(root.getListOfValuesInOrder());