将二进制搜索树转换为双向链接列表 - 不起作用

时间:2014-08-03 04:57:19

标签: java algorithm linked-list binary-search-tree

我粘贴的解决方案来自 this Geek URL

用C语言编写,所以我尝试在JAVA中将其转换如下 - (如果我错了,请纠正我,我不是c/c++

程序

   // A simple recursive function to convert a given Binary tree to Doubly
   // Linked List
   // root --> Root of Binary Tree
   // head --> Pointer to head node of created doubly linked list
   public void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes head)
   {
           if(root == null)
               return;

           // Initialize previously visited node as NULL. This is
           // declared outside the recursive function so that the same value 
           // is accessible in all recursive calls   

            prev = null;

            // Recursively convert left subtree
            BinaryTree2DoubleLinkedList(root.getLeft(), head);

            //set head of LL if not set
            if(orgHead == null)
                orgHead = root;

            // Now convert this node
            if (prev == null)
                head = root;
            else
            {
                root.setLeft(prev);
                prev.setRight(root);
            }
            prev = root;

            // Finally convert right subtree
            BinaryTree2DoubleLinkedList(root.getRight(), head);
    }

考虑中的树

            10
          /   \
         5    15
        / \  /   \
       2  7 12   18
      /
     1
    /
   0

问题

该程序返回输出:

0 1 2 5 7 10 15 18

正如您所看到的,代码中缺少12。我试图干了很多次,但仍然无法找到真正的问题.....我尝试寻找不同的解决方案,但大多数它们遍历 part-converted-LL ,这增加了时间复杂度。

6 个答案:

答案 0 :(得分:4)

在原始C代码中,函数原型如下:

void BinaryTree2DoubleLinkedList(node *root, node **head)

**头部意味着双指针,头部值可以使用* head在函数内改变。在java中,您无法修改函数参数,因为它们始终被复制,但您可以修改数组元素。 所以请尝试以下代码:

BTNode prev;

void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes[] head)
{
    // Base case
    if (root == null) return;

    // Initialize previously visited node as NULL. This is
    // static so that the same value is accessible in all recursive
    // calls

    // Recursively convert left subtree
    BinaryTree2DoubleLinkedList(roor.getLeft(), head);

    // Now convert this node
    if (prev == null)
        head[0] = root;
    else
    {
        root.setLeft(prev);
        prev.setRight(root);
    }
    prev = root;

    // Finally convert right subtree
    BinaryTree2DoubleLinkedList(root.getRight(), head);
}

初始通话应如下所示:

BTNodes[] head = new BTNodes[1];
BinaryTree2DoubleLinkedList(root, head);
// result is in head[0]

为避免头部元素的丑陋分配,更好地制作如下的附加功能:

BTNodes BinaryTree2DoubleLinkedList(BTNodes root) {
    BTNodes[] head = new BTNodes[1];
    BinaryTree2DoubleLinkedList(root, head);
    return head[0];
}

答案 1 :(得分:2)

如果我们使用Node的左右字段,将二进制搜索树转换为双链接列表是一件容易的事。 递归帮助我们。

  • 首先,向下走到左边的节点。将最左侧的叶节点分配为prev以及列表的头部。
  • 一旦控制从叶节点返回到其父节点,则将当前节点即左节点的父节点指定为prev的右侧,将当前节点的左侧指定为叶节点。 同样适用于当前节点的右叶子。
  • 一旦我们完成递归,我们将获得带有listHead和listTail的双链表。

{

Node prev = null;
Node listHead = null;
Node listTail = null;
public void convertToList(Node node)
{
    if(node == null)
        return;
    convertToList(node.left);
    if(listHead == null)
        listHead = node;
    if(prev == null)
        prev = node;
    else
    {
        node.left = prev;
        prev.right = node;
    }
    prev = node;
    convertToList(node.right);
    if(node.right == null)
        listTail = node;

}
public void printList()
{
    Node node = listHead;
    System.out.println("Doubly Linked List from Head: ");
    while(node!= null)
    {
        System.out.print(node.data+" ");
        node = node.right;
    }
}
public void printListFromTail()
{
    Node node = listTail;
    System.out.println("Doubly Linked List from Tail: ");
    while(node!= null)
    {
        System.out.print(node.data+" ");
        node = node.left;
    }
}

}

答案 2 :(得分:0)

对于任何Google访问者,我找到了一种避免head[0]的方法 - (如果通过不同树的不同对象调用该程序,则可能会出现问题,因为head[0]可能会被覆盖

以下是实施:

Trick是从代码中删除prev = null;并在调用函数中初始化tempHead = nullprev = null,而不是在递归调用中。

void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes tempHead)
       {
           // Base case
           if (root == null) return; //optional, not needed in fact

           // Recursively convert left subtree
           if(root.getLeft() != null) //purely to reduce number of traversed node
               BinaryTree2DoubleLinkedList(root.getLeft(), tempHead);

          //set Original Head of the List, this would be leftmost
          //leaf in the tree
           if(orgHead == null) 
               orgHead = root;

           // Now convert this node
           if (prev == null)
               tempHead = root;
           else
           {
               root.setLeft(prev);
               prev.setRight(root);
           }
           prev = root;

           // Finally convert right subtree
           if(root.getRight() != null) //purely to reduce number of traversed node
               BinaryTree2DoubleLinkedList(root.getRight(), tempHead);
       }

其他助手详情:

初次通话:

BinaryTree2DoubleLinkedList(bst.root,tempHead); //root and null value

遍历列表

printList(orgHead); //pass original head to print function

复杂性:

Time = Space : O(n)

答案 3 :(得分:0)

 public  void  ConverttoList(Node root){
    Node top = root;
    top.left = GetLeftNode(top.left);
    top.right = GetRightNode(top.right);
    top.left.right= top;
    top.right.left= top;
    Node leftmost = top.left;
    while(leftmost.left!=null){
        leftmost = leftmost.left;
    }
    while(leftmost!= null) {
        System.out.printf(leftmost.Data + "->");
        leftmost = leftmost.right;
    }

}

public Node GetLeftNode(Node root){
    if(root.left == null){
        return root;
    }
    else{
        Node startnode = GetLeftNode(root.left);
        startnode.right = root;
        root.left = startnode;
        root.right = GetRightNode(root.right);
        root.right.left = root;
        Node rightmost=root.right;
        while (rightmost.right!=null){
            rightmost=rightmost.right;
        }
        return rightmost;
    }
}

public  Node GetRightNode(Node root){
    if(root.left == null){
        return root;
    }
    else{
        Node startnode = GetLeftNode(root.left);
        startnode.right = root;
        root.left = startnode;
        root.right = GetRightNode(root.right);
        root.right.left = root;
        Node leftmost=root.left;
        while (leftmost.left!=null){
            leftmost=leftmost.left;
        }
        return leftmost;
    }
}

答案 4 :(得分:0)

// bst to dll will generate a sorted dll
public class TreeToDLL {
    public static void main(String args[]){
        TreeNode t = new TreeNode(5);
        TreeNode t3 = new TreeNode(3);
        TreeNode t1 = new TreeNode(1);
        TreeNode t7 = new TreeNode(7);
        TreeNode t9 = new TreeNode(9);
        TreeNode t8 = new TreeNode(8);
        t.setLeft(t3);
        t3.setLeft(t1);
        t.setRight(t7);
        t7.setRight(t9);
        t9.setLeft(t8);
        DllNode dll = convert(t);
        dll.print();
    }
    static class DllNode{
        int data;
        DllNode next;
        DllNode prev;

        public DllNode(int data) {
            this.data = data;
        }
        public DllNode() {
        }
        public int getData() {
            return data;
        }
        public DllNode getPrev() {
            return prev;
        }
        public void setPrev(DllNode prev) {
            this.prev = prev;
        }

        public void setData(int data) {
            this.data = data;
        }
        public DllNode getNext() {
            return next;
        }
        public void setNext(DllNode next) {
            this.next = next;
        }
        public void print(){
            DllNode t = this;
            while(t!=null){
                System.out.print(t.getData()+"->");
                t = t.getNext();
            }
        }
    }
    static class TreeNode{
        int data;
        TreeNode left;
        TreeNode right;

        public TreeNode(int data) {
            this.data = data;
        }

        public int getData() {
            return data;
        }

        public void setData(int data) {
            this.data = data;
        }

        public TreeNode getLeft() {
            return left;
        }

        public TreeNode setLeft(TreeNode left) {
            this.left = left;
            return this;
        }

        public TreeNode getRight() {
            return right;
        }

        public TreeNode setRight(TreeNode right) {
            this.right = right;
            return this;
        }
    }

    private static DllNode convert(TreeNode t){
        DllNode d =convert(t,new PreviousDLLNode());
        while(d.prev!=null){
            d = d.prev;
        }
        return d;
    }
    private static DllNode convert(TreeNode t, PreviousDLLNode d){
        if(t==null) return null;
        convert(t.getLeft(),d);
        DllNode dn = new DllNode(t.getData());
        if(d.val!=null){
            d.val.setNext(dn);
        }
        dn.setPrev(d.val);
        d.val = dn;
        convert(t.getRight(),d);
        return dn; // this node will be in the middle of the dll.
    }
    private static class PreviousDLLNode{
        DllNode val;
    }
}

答案 5 :(得分:0)

我解决了插入treenodes的问题,这些按顺序排列在这样的DLL中:

  1. 我在netBeans包中添加了所需的DoubleLinkedList和BinarySearchTree类(包括TreeNode和DoubleNode等)和
  2. 我修改了BinarySearchTree,如下所示:

    select forum.title, count(comment.post_id) as count from (select * from post where parent_post_id = -1) as forum
      left outer join post as topic on topic.parent_post_id = forum.post_id
      left outer join post as comment on comment.parent_post_id = topic.post_id
      group by forum.title
    
  3. 我添加了一个DoubleLinkedList字段,我在BST的默认构造函数中初始化,调用DLL的默认构造函数,我创建了下面的递归方法,灵感来自于inOrderTraversal,用于DLL中树节点的排序输入