конструкция бинарного дерева из предзаказа - PullRequest
4 голосов
/ 16 марта 2011

Это вопрос интервью Amazon. Кто-нибудь может дать алгоритм для этого?

Существует двоичное дерево со следующими свойствами:

  • Все его внутренние узлы имеют значение 'N', а все листья имеют значение 'L'.
  • Каждый узел либо имеет двух дочерних, либо не имеет дочерних.

Учитывая его предварительный порядок, построить дерево и вернуть корневой узел.

Ответы [ 5 ]

3 голосов
/ 16 марта 2011

Поскольку гарантируется, что каждый внутренний узел имеет ровно 2 дочерних элемента, мы можем просто рекурсивно построить дерево, используя это.

Мы вызываем нашу функцию с предоставленным вводом, и она проверяет первый полученный символ. Если это листовой узел, он просто возвращает лист. Если это внутренний узел, он просто вызывает себя для левого и правого поддеревьев и возвращает дерево, сформированное с использованием узла в качестве корня, а левое и правое поддеревья - в качестве его левого и правого потомков.

Код следует (на Python). Обратите внимание, я использую tuple s для представления узла, поэтому дерево имеет значение tuple из tuples.

#! /usr/bin/env python
from collections import deque

def build_tree(pre_order):
        root=pre_order.popleft()
        if root=='L':
                return root
        else:
                return (root,build_tree(pre_order),build_tree(pre_order))

if __name__=='__main__':
        print build_tree(deque("NNLLL"))

Редактировать: код в Java

import java.util.*;
class Preorder{
        public static Node buildTree(List<Character> preorder){
                char token=preorder.remove(0);
                if (token=='L'){
                        return new Node(token,null,null);
                }
                else{
                        return new Node(token,buildTree(preorder),buildTree(preorder));

                }
        }
        public static void main(String args[]){
                List<Character> tokens=new LinkedList<Character>();
                String input="NNLLL";
                for(int i=0;i<input.length();i++) tokens.add(input.charAt(i));
                System.out.println(buildTree(tokens));
        }
}

class Node{
        char value;
        Node left,right;
        public Node(char value, Node left, Node right){
                this.value=value;
                this.left=left;
                this.right=right;
        }

        public String toString(){
                if (left==null && right==null){
                        return "("+value+")";
                }
                else{
                        return "("+value+", "+left+", "+right+")";
                }
        }
}
0 голосов
/ 20 июня 2018

Функция construct выполняет фактическое построение дерева.Фрагмент кода - это решение вопроса GeeksforGeeks, о котором вы упомянули, как указано выше.

    struct Node*construct(int &index, Node*root, int pre[], int n, char preLN[])
{   
    Node*nodeptr;
    if(index==n)
    {
        return NULL;
    }
    if(root==NULL)
    {
        nodeptr = newNode(pre[index]);
    }
    if(preLN[index]=='N')
    {   
        index = index+1;
        nodeptr->left = construct(index, nodeptr->left, pre,n,preLN);
        index = index+1;
        nodeptr->right = construct(index, nodeptr->right,pre,n,preLN);
        return nodeptr;
    }
    return nodeptr;
}
struct Node *constructTree(int n, int pre[], char preLN[])
{   
    int index =0;
    Node*root = construct(index,NULL,pre,n,preLN);
    return root;
}

Указывает на примечание:

  1. Индекс объявлен ссылочной переменной, так чтовернувшись к родительскому узлу, функция начинает строить дерево из общего последнего значения индекса , а не из значения индекса, которым обладает функция при первоначальном выполнении вызова.

  2. Различные значения индекса для правого и левого поддеревьев, поскольку обход предварительного порядка следует за последовательностью узлов Root, Left, Right.

Надеюсь, что это поможет.

0 голосов
/ 18 марта 2011

Вот Java-программа ::

import java.util. *;

класс preorder_given_NNNLL {

static Stack<node> stk = new Stack<node>();
static node root=null;

  static class node
  {
      char value;
      node left;
     node right;
      public node(char value)
      {
              this.value=value;
              this.left=null;
              this.right=null;
      }


  }

  public static node stkoper()
  {
      node posr=null,posn=null,posl=null;
      posr=stk.pop();
      if(stk.empty())
      {
          stk.push(posr);
          return null;
      }
      else
          posl=stk.pop();

      if(stk.empty())
      {
          stk.push(posl);
          stk.push(posr);
          return null;

      }
      else
      {
          posn=stk.pop();
      }


      if( posn.value == 'N' && posl.value == 'L' && posr.value == 'L')
      {

          root = buildtree(posn, posl, posr);

          if(stk.empty())
          {
              return root;

          }
          else
          {
              stk.push(root);


              root=stkoper();
          }
      }
      else
      {
          stk.push(posn);
          stk.push(posl);
          stk.push(posr);
      }
    return root;


  }


  public static node buildtree(node posn,node posl,node posr)
  {         
      posn.left=posl;
      posn.right=posr;
      posn.value='L';
      return posn;

  }

  public static void inorder(node root)
    {
        if(root!=null)
        {
            inorder(root.left);
            if((root.left == null) && (root.right == null))
                System.out.println("L");
            else
                System.out.println("N");
            inorder(root.right);
        }
}

  public static void main(String args[]){

          String input="NNNLLLNLL";
          char[] pre = input.toCharArray();
         for (int i = 0; i < pre.length; i++) 
         {
            node temp = new node(pre[i]);
            stk.push(temp);
            root=stkoper();
         }

         inorder(root);

  }

}

0 голосов
/ 16 марта 2011

Я думаю, что ключевым моментом является осознание того, что есть три возможности для соседних узлов: NN, NL ?, L? (``? '' означает либо N, либо L)

  1. NN: второй N - это левый потомок первого N, но мы не знаем, что является правым потомком первого N *
  2. NL ?: второй N - левый потомок первого N, а правый потомок первого N -?
  3. L ?:? правильный ребенок STACK top

STACK используется потому, что когда мы читаем узел в последовательности предварительного заказа, мы не знаем, где находится его правый дочерний элемент (мы знаем, где находится его левый дочерний элемент, если он у него есть). STACK хранит этот узел так, что когда появляется его правый дочерний элемент, мы можем открыть его и завершить правую ссылку.

NODE * preorder2tree(void)
{
    NODE * head = next_node();
    NODE * p = head;
    NODE * q;

    while (1) {
            q = next_node();
            if (!q)
                    break;

            /* possibilities of adjacent nodes:
             * NN, NL?, L?
             */
            if (p->val == 'N') {
                    p->L = q;
                    if (q->val == 'N') { /* NN */
                            push(p);
                            p = q;
                    } else {             /* NL? */
                            q = next_node();
                            p->R = q;
                            p = q;
                    }
            } else {                     /* L? */
                    p = pop();
                    p->R = q;
                    p = q;
            }
    }
    return head;
}

Код выше был протестирован с использованием нескольких простых случаев. Надеюсь, это правильно.

0 голосов
/ 16 марта 2011

Я могу вспомнить рекурсивный алгоритм.

head = новый узел.удалить первый символ в preorderString
Invoke f(head, preorderString)

Рекурсивная функция f(node, s)
- удалить первый символ из s, если L затем присоединить к узлу в виде листа.
elseсоздать nodeLeft, присоединиться к узлу, вызвать f (nodeLeft, s)
- удалить первый символ из s, если L, затем присоединиться к узлу в виде листа.
иначе создать nodeRight, присоединиться к узлу, вызвать f(nodeRight, s)

...