将已排序的双向链表转换为BST

时间:2011-10-24 10:52:35

标签: algorithm binary-tree doubly-linked-list

如何将已排序的双向链表转换为平衡二进制搜索树。

我在想这样做就像将数组转换为平衡的BST一样。 找到中心,然后递归转换DLL的左侧部分和右侧部分。 例如,

1 2 3 4 5 => 1 2 (3) 4 5 =>

     3
   /   \
  2     4
 /       \
1         5

这导致重现T(n)= 2T(n / 2)+ O(n)。 O(n)用于寻找中心。 因此,时间复杂度为O(nlogn)。 我想知道是否有一个算法在O(n)中执行此操作。

3 个答案:

答案 0 :(得分:3)

是的,有O(n)解决方案。请注意,BST上的in-order traversal是按所需顺序迭代元素,因此只需在最初为空的大小为的树上进行 inorder遍历,并在其中填充元素名单。 [在遍历中插入树中的第i个元素是列表中的第i个元素]。
在答案的最后,我添加了如何在O(n)中创建一个空的平衡树。

伪代码:[假设|列表| == |树|]

global current <- null
fillTree(tree,list):
  current <- list.head
  fillTree(tree)
fillTree(tree):
  if tree == null:
     return
  fillTree(tree.left)
  //in-order traversal: we set the value after setting left, and before calling right
  tree.val <- current.val
  current <- current.next
  fillTree(tree.right)

复杂性很简单O(n),因为树的每个顶点都有一个迭代,每次迭代都是O(1)。

修改
您可以创建一个空的平衡树,只需构建一个空的complete tree(*),它就是平衡的,并且构建它是O(n)。

(*)完整的二叉树是一个二叉树,其中除了可能是最后一个级别之外,每个级别都被完全填充。

答案 1 :(得分:1)

差不多4年了。但这是我的功能解决方案。以下是我在haskell中的代码,复杂度也是O(n)

import Data.List hiding (insert)

data Color = R | B deriving Show
data RBTree a = RBEmpty | RBTree { color :: Color
                                 , ltree :: RBTree a
                                 , nod   :: a
                                 , rtree :: RBTree a } deriving Show

fromOrdList ::  Ord e => [e] -> RBTree e
fromOrdList [] = empty
fromOrdList lst = 
    let (res, _) = _fol lst $ length lst
    in res
    where _fol :: (Ord e, Integral a) => [e] -> a -> (RBTree e, Maybe (e, [e]))
          _fol l 0            = (empty, uncons l)
          _fol (h:l) 1        = (RBTree B empty h empty, uncons l)
          _fol (h1:h2:l) 2    = (RBTree B (RBTree R empty h1 empty) h2 empty, uncons l)
          _fol (h1:h2:h3:l) 3 = (RBTree B (RBTree R empty h1 empty) h2 (RBTree R empty h3 empty), uncons l)
          _fol l n            =
            let mid                  = n `div` 2
                (ltr, Just (rt, tl)) = _fol l mid
                (rtr, mayremain)     = _fol tl (n - 1 - mid)
in (RBTree B ltr rt rtr, mayremain)

这实际上是我个人实践的一部分:https://github.com/HuStmpHrrr/PFDSPractise/blob/master/src/Tree/RBTree.hs#L97

答案 2 :(得分:0)

看看我的递归插入实现(c#)。存在T(n)= 2 * T(n / 2)+ O(1)。 O(1)用于找到中心:(l + r)/ 2。因此,共谋是O(n)

public class Tree<T>
  {
    public class TreeNode<T>
    {
      public TreeNode<T> Right { get; set; }
      public TreeNode<T> Left { get; set; }
      public T Data { get; set; }
    }

    public Tree()
    {
      Root = new TreeNode<T>();
    }  

    public TreeNode<T> Root { get; set; }

    private void InsertSortedListRec(IList<T> items, TreeNode<T> curNode, int l, int r)
    {
      var mid = (l + r)/2;
      curNode.Data = items[mid];

      if (mid - 1 >= l)
      {
        curNode.Left = new TreeNode<T>();
        InsertSortedListRec(items, curNode.Left, l, mid - 1);
      }

      if (mid + 1 <= r)
      {
        curNode.Right = new TreeNode<T>();
        InsertSortedListRec(items, curNode.Right, mid + 1, r);
      }
  }

    public void InsertSortedList(IList<T> items)
    {
      InsertSortedListRec(items, Root, 0, items.Count - 1);
    }
  }

我假设我们有索引数组(我们可以将链表转换为数组O(n))