2

这是第 2 轮亚马逊面试问题。将给定的二叉搜索树转换为预购和后购链表,并且必须进行这种转换

4

5 回答 5

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);
   }
于 2016-07-03T11:58:18.293 回答
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;
}
于 2014-07-29T08:38:23.800 回答
0
void preorder(struct node *head)
{

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

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

全球宣言

struct node *llHead;

这样链表头就完好无损。

于 2014-07-28T12:53:56.163 回答
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;
于 2014-08-04T13:36:36.543 回答
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;
 }

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

于 2016-07-03T11:15:49.767 回答