将BST转换为预订和后序链接列表

时间:2014-07-25 17:43:10

标签: linked-list binary-search-tree in-place preorder postorder

这是亚马逊的第二轮采访问题。将给定的二进制搜索树转换为预订和订购后链接列表,此转换必须就地

5 个答案:

答案 0 :(得分:3)

编写下面的代码是为了在不使用堆栈的情况下以预先顺序遍历形式对二叉树进行展平。它使用pre-order遍历递归方法。在这里,TreeNode [] arr将保存我正在更新该节点的右指针的最后一个最左边的节点值。

    public TreeNode preorderNode(TreeNode root,TreeNode[] arr)
    {
    if(root==null)
        return null;
    if(root!=null && root.left==null && root.right==null)    
        {
            arr[0]=root;
            return root;
        }
    TreeNode temp=root.right;
    if(root.left!=null)
        root.right=preorderNode(root.left,arr);
    else arr[0]=root;
    root.left=null;
    arr[0].right=preorderNode(temp,arr);
    return root;
    }
    public void flatten(TreeNode root) {

        if(root==null || (root.left==null && root.right==null))
            return;
        TreeNode temp=root.right;    
        TreeNode[] arr=new TreeNode[1];
        arr[0]=null;
        if(root.left!= null)
            root.right=preorderNode(root.left,arr);
        else
            arr[0]=root;
        root.left=null;
       arr[0].right=preorderNode(temp,arr);
   }

答案 1 :(得分:1)

要解决问题的预订版本,您可以稍微修改一个简单的预订单(请参阅下面的代码来查看)。

这个想法是在前序遍历中从二叉搜索树构造一个双向链表。但是,我们只在遍历期间设置了前向链接。

让我们通过一个例子来学习。 如果树看起来像:

        4
       / \
      2   6
     / \ / \
    1  3 5  7

然后,链表应如下所示:

4< - > 2 - < - > 1 - < - > 3 - < - > 6 - < - > 5 - < - > 7。

现在,我们只在前序遍历期间设置了前向链接。因此,我们的列表看起来像。

4 - > 2 - > 1 - > 3 - > 6 - > 5 - > 7

左侧或上一个指针(上面未显示)仍然与它们在树中一样。 我们现在可以通过对列表的简单遍历来设置左指针。

以下代码就是这样做的。

#include <iostream>
using namespace std;

class node{
    public:
        int data;
        node * left, *right;
        node(int a){
            data = a;
            left = right = NULL;
        }
};

node * head = NULL, *prev = NULL;

void preorder(node * root){
    if(!root)   return;

    //both head and prev aren't set. This node must be the root(and head of our required list).
    if(!head and !prev) head = root;    

    //store the address of root's right child
    node * temp = root->right;

    /*
        If prev is set, make current node it's right child.
        (This is why we save right child's address for every node in temp.)
    */
    if(prev)    prev->right = root;

    //now make the current node prev.
    prev = root;
    cout << root ->data <<" ";

    preorder(root->left);
    preorder(temp);
}

void printll(){
    node * prev = NULL;
    while(head != NULL){
        cout << head ->data << " ";
        head -> left = prev;
        head = head -> right;
        prev = head;
    }
    cout<<endl;
}

int main() {

    node * t = new node(4);

    t->left = new node(2);
    t->left->left = new node(1);
    t->left->right = new node(3);

    t->right = new node(6);
    t->right->left = new node(5);
    t->right->right = new node(7);

    preorder(t);
    cout<<endl;
    printll();
    return 0;
}

答案 2 :(得分:0)

void preorder(struct node *head)
{

if (head)
    {
        addToLL(head->data);
        preorder(head->left);
        preorder(head->right);
    }
}

在addToLL()中,您可以继续将节点添加到链接列表中。

全球宣言

struct node *llHead;

这样链表头就完好了。

答案 3 :(得分:0)

以下算法用于预订转换。同样,你也可以进行下订单。

 struct node
    {
        int data;
        struct node* left;
        struct node* right;
    };

    /Algorithm */
    struct node* bintree2listHelper(struct node *root)
    {
       if (root == NULL)
          return root;

       if (root->left != NULL)
       {
          struct node* left = bintree2listHelper(root->left);

          int flag =0;
     if(left->left == NULL)
    {
       left->left = left->right;
    }



          for(;left->left != NULL;)
          {
             struct node *temp = left;

             for (; temp->right!=NULL; )
             {
                flag = 1;
                temp=temp->right;
             }
             if(flag)
             {
                temp->left = root->right;
                left =left->left;
                break;
             }
             else
             {
                left =left->left;
             }

          }

          if(!flag)
             left->left = root->right;
       }

       if (root->right!=NULL)
       {
          struct node* right = bintree2listHelper(root->right);

          struct node *temp1= right;

          for (; right->left!=NULL; )
          {
             temp1 =right;
             right = right->left;
          }


          right->left = temp1->right;
       }
       return root;
    }

    struct node* bintreeTolist(struct node *root)
    {
        if (root == NULL)
            return root;

        root = bintree2listHelper(root);

        return (root);
    }

    struct node* newNode(int data)
    {
        struct node* new_node = (struct node *)malloc(sizeof(struct node));
        new_node->data = data;
        new_node->left = new_node->right = NULL;
        return (new_node);
    }

    void printList(struct node *node)
    {
        while (node!=NULL)
        {
            printf("%d ", node->data);
            node = node->left;
        }
        printf("\n");
    }
int main()
{
    typedef struct node node;
    node *root        = newNode(10);
    root->left        = newNode(12);
    root->right       = newNode(15);
    root->left->left  = newNode(25);
    root->left->right = newNode(30);
    root->right->left = newNode(36);
    root->left->right->left = newNode(78);
    root->left->right->right = newNode(77);
 node *head = bintreeTolist(root);

    // Print the converted list

   printList(head);
return 0;

答案 4 :(得分:0)

预订链接列表

 public TreeNode flatten(TreeNode root) {
    if(root==null)
        return null;
    Stack<TreeNode> s=new Stack<TreeNode>();
    s.add(root);
    while(!s.isEmpty()){
        root=s.pop();
        if(root.right!=null)
            s.add(root.right);
        if(root.left!=null)
            s.add(root.left);
        if(!s.isEmpty())
            root.right=s.peek();
        else
            root.right=null;
        root.left=null;
    }
    return root;
 }

上面的代码给出了预订链表,右指针作为下一个指针,左指针被忽略(即设置为空)。它是迭代预订遍历代码的略微修改 想法是,一旦完成当前节点的处理,堆栈顶部就会有链接列表中当前节点的下一个节点。