平衡BST

时间:2012-12-22 09:31:08

标签: algorithm data-structures binary-search-tree

参考: 我被问到这个问题@MS SDE采访,第3轮。这不是一个家庭作业问题。我也考虑了一下,并在下面提到我的方法。

问题: 修改BST以使其尽可能平衡。不用说,你应该尽可能高效。

提示: 采访者说这是一个合乎逻辑的问题,如果你有不同的想法,你会得到答案。没有困难的编码。
- >话虽如此,我认为他不指望我指向AVL / RB树。

我的解决方案: 我建议,我会按顺序遍历树,把中间元素作为新树的根(让我们称之为新的根)。然后转到中间元素的左侧部分,将其中间元素作为树根新子根的左子树的根。同样适用于正确的部分。 递归执行此操作将提供最佳的平衡BST。

我为什么要在此发帖: 但他对答案并不满意:(那么,真的有一种方法可以做这个没有用于权重/ RB着色策略,还是他只是在骗我? 请加入你的专家意见。

重复?不! 我知道有这个question但是请求者提出的解决方案太复杂了,其他人讨论了AVL树。

4 个答案:

答案 0 :(得分:38)

您可能需要查看 Day-Stout-Warren 算法,该算法是一种O(n)-time,O(1)空间算法,用于将任意二进制搜索树重新整形为完整的二叉树。直觉上,该算法的工作原理如下:

  1. 使用树旋转,将树转换为退化链表。
  2. 通过将选择性旋转应用于链表,将列表转换回完全平衡的树。
  3. 这种算法的优点在于它在线性时间内运行,只需要恒定的内存开销;事实上,它只是重塑了底层树,而不是创建一个新树并复制旧数据。编码也相对简单。

    希望这有帮助!

答案 1 :(得分:15)

“尽可能平衡”= complete (or full) binary tree 1 。你无法更加平衡它。

解决方案很简单 - 构建一个“空”完整二叉树,并在inorder-traversal中迭代新树和输入树(同时)以填充整个树。

完成后,您可以获得最平衡的树,此方法的时间复杂度为O(n)


修改
这应该按照以下步骤完成:

  1. 使用n个节点构建虚拟完整树。每个的所有值 节点将被初始化为一些垃圾值。
  2. 创建两个迭代器:(1)originalIter用于原始树,(2)newIter用于新(用垃圾初始化)树。两个迭代器都将按顺序遍历返回元素。
  3. 执行以下操作以使用原始值填充树:

     while (originalIter.hasNext()):
          newIter.next().value = originalIter.next().value
    

  4. (1)(来自维基百科):一个完整​​的二叉树是一个二叉树,其中除了可能是最后一个级别之外,每个级别都被完全填充,并且所有节点都尽可能地离开

答案 2 :(得分:10)

DSW算法可以解决这个O(n)时间问题。算法如下:

1] Using right-rotation operations, turn the tree into a linked list
   (a.k.a. backbone or vine)
2] Rotate every second node of the backbone about its parent to turn
   the backbone into a perfectly balanced BST. 

Reference

答案 3 :(得分:1)

这会将您的常规BST转换为平衡的BST,且其最小高度可能为O(n)。首先,将所有节点保存到向量中。然后,根是mid元素,并递归地在0到mid-1的左边建立一棵树,并在mid + 1到vector.size()-1的树作为右边的孩子。完成所有这些步骤后,root会保持平衡的BST与最小高度。

    import java.util.Vector;

        public class ConvertBSTIntoBalanced {

            public static void main(String[] args) {
                TreeNode node1 = new TreeNode(1);
                TreeNode node2 = new TreeNode(2);
                TreeNode node3 = new TreeNode(3);
                TreeNode node4 = new TreeNode(4);
                node1.right = node2;
                node2.right = node3;
                node3.right = node4;
                ConvertBSTIntoBalanced convertBSTIntoBalanced = new ConvertBSTIntoBalanced();
                TreeNode balancedBSTRoot = convertBSTIntoBalanced.balanceBST(node1);
            }

            private void saveNodes(TreeNode node, Vector<TreeNode> nodes) {
                if (node == null)
                    return;
                saveNodes(node.left, nodes);
                nodes.add(node);
                saveNodes(node.right, nodes);
            }

            private TreeNode buildTree(Vector<TreeNode> nodes, int start, int end) {
                if (start > end)
                    return null;
                int mid = (start + end) / 2;
                TreeNode midNode = nodes.get(mid);
                midNode.left = buildTree(nodes, start, mid - 1);
                midNode.right = buildTree(nodes, mid + 1, end);
                return midNode;
            }

            public TreeNode balanceBST(TreeNode root) {
                Vector<TreeNode> nodes = new Vector<>();
                saveNodes(root, nodes);
                return buildTree(nodes, 0, nodes.size() - 1);
            }

        public class TreeNode {

        public Integer val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(Integer x) {
            val = x;
        }

    }

        }

我希望它会有所帮助。