Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 由前序构造二叉树_Algorithm_Binary Tree - Fatal编程技术网

Algorithm 由前序构造二叉树

Algorithm 由前序构造二叉树,algorithm,binary-tree,Algorithm,Binary Tree,这是一个亚马逊采访问题。有谁能给出一个算法来做到这一点 存在具有以下属性的二叉树: 它的所有内部节点都有值'N',所有叶子都有值'L' 每个节点要么有两个子节点,要么没有子节点 给定其前序,构造树并返回根节点。我可以想到一种递归算法 head=新节点。 删除预排序字符串中的第一个字符 调用f(head,preorderString) 递归函数f(节点,s) -从s中删除第一个字符,如果L,则将其作为叶附加到节点。 否则创建一个nodeLeft,附加到节点,调用f(nodeLeft,s) -从

这是一个亚马逊采访问题。有谁能给出一个算法来做到这一点

存在具有以下属性的二叉树:

  • 它的所有内部节点都有值
    'N'
    ,所有叶子都有值
    'L'
  • 每个节点要么有两个子节点,要么没有子节点

给定其前序,构造树并返回根节点。

我可以想到一种递归算法

head
=新节点。 删除
预排序字符串中的第一个字符
调用
f(head,preorderString)

递归函数
f(节点,s)

-从s中删除第一个字符,如果
L
,则将其作为叶附加到节点。
否则创建一个nodeLeft,附加到节点,调用f(nodeLeft,s)
-从s中删除第一个字符,如果
L
,则将其作为叶附加到节点。

否则创建一个noderlight,附加到节点,调用f(noderlight,s)

由于保证每个内部节点正好有2个子节点,我们可以简单地使用它递归地构建树

我们使用提供的输入调用函数,它检查得到的第一个字符。如果它是一个叶节点,它只返回一个叶。如果它是一个内部节点,它只调用自己的左、右子树,并返回使用该节点作为根、左、右子树作为左、右子树形成的树

代码如下(在Python中)。注意,我使用
tuple
s表示节点,因此树是
tuple
tuple

#! /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+")";
                }
        }
}
import java.util.*;
类前序{
公共静态节点构建树(列表预排序){
char-token=preorder.remove(0);
如果(标记=='L'){
返回新节点(令牌,空,空);
}
否则{
返回新节点(令牌、buildTree(预订单)、buildTree(预订单));
}
}
公共静态void main(字符串参数[]){
列表标记=新的LinkedList();
字符串输入=“NNLLL”;

对于(int i=0;i我认为关键点是认识到相邻节点有三种可能性:NN、NL?、L?(`?''表示N或L)

  • NN:第二个N是第一个N的左子代,但我们不知道第一个N的右子代是什么
  • NL?:第二个N是第一个N的左子级,第一个N的右子级是
  • L:?是堆栈顶部的正确子级
  • 之所以使用堆栈,是因为当我们在预排序序列中读取一个节点时,我们不知道它的右子节点在哪里(我们知道它的左子节点在哪里,只要它有一个)。堆栈存储该节点,以便当它的右子节点出现时,我们可以弹出它并完成它的右链接

    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;
    }
    

    上面的代码是使用一些简单的案例进行测试的。希望它是正确的。

    以下是java程序:

    导入java.util.*

    类预排序\u给定\u NNNLL {

    static Stack stk=new Stack();
    静态节点根=null;
    静态类节点
    {
    字符值;
    左淋巴结;
    节点权;
    公共节点(字符值)
    {
    这个。值=值;
    this.left=null;
    this.right=null;
    }
    }
    公共静态节点stkoper()
    {
    节点posr=null,posn=null,posl=null;
    posr=stk.pop();
    if(stk.empty())
    {
    stk.push(posr);
    返回null;
    }
    其他的
    posl=stk.pop();
    if(stk.empty())
    {
    stk.push(posl);
    stk.push(posr);
    返回null;
    }
    其他的
    {
    posn=stk.pop();
    }
    如果(posn.value='N'&&posl.value='L'&&posr.value='L')
    {
    root=buildtree(posn、posl、posr);
    if(stk.empty())
    {
    返回根;
    }
    其他的
    {
    stk.push(根);
    root=stkoper();
    }
    }
    其他的
    {
    stk.push(posn);
    stk.push(posl);
    stk.push(posr);
    }
    返回根;
    }
    公共静态节点构建树(节点posn、节点posl、节点posr)
    {         
    posn.left=posl;
    posn.right=posr;
    posn.value='L';
    返回posn;
    }
    公共静态无效序(节点根)
    {
    if(root!=null)
    {
    顺序(根。左);
    if((root.left==null)和&(root.right==null))
    系统输出打印项次(“L”);
    其他的
    系统输出打印项次(“N”);
    顺序(root.right);
    }
    }
    公共静态void main(字符串参数[]){
    字符串输入=“nnnllll”;
    char[]pre=input.toCharArray();
    对于(int i=0;i

    }

    构造函数执行实际的树构造。代码片段是您上面提到的Geeksforgeks问题的解决方案

        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;
    }
    
    注意事项:

  • 索引已声明为引用变量,因此在返回到父节点时,函数将从索引的总体最新值开始构建树,而不是从最初执行调用时函数所拥有的索引值开始构建树

  • 由于前序遍历遵循节点的根、左、右序列,所以左右子树的索引值不同


  • 希望能有所帮助。

    你真的应该了解数据结构,但预顺序只是根、左节点、右节点。@TrevorMA-这是真的,但这不是问题所在。想法是如何在给定遍历的情况下重建树,这要求你知道的不仅仅是预顺序。如果你能用java或c提供代码,它将太好了。提前谢谢。@Nohsib:co补充道
        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;
    }