如何从preorder和inorder遍历构建二叉树

时间:2011-03-06 20:11:00

标签: java binary-tree

我正在做一个关于从预订和顺序遍历构建二叉树的任务(每个节点中的一个字符),我试图将我的大脑包围在如何构建实际树。

以下是关于如何实现这一目标的思考过程:

  1. 将预订中的第一个条目存储为根节点
  2. 搜索该条目的顺序。
  3. 将字符放在根节点的左侧,并将它们保存为字符数组。
  4. 将字符放在根节点的右侧,并将它们保存为字符数组。
  5. 创建一个新树,以root为父,其中2个子为左右char数组。
  6. 继续递归,直到预订长度为0。
  7. 我已经完成了步骤1-4,但我不太确定如何正确构建我的树,并且想知道是否有人有任何指针。谢谢。

5 个答案:

答案 0 :(得分:5)

在构建新树之前进行递归。所以,你的清单看起来像这样:

  1. 如果数组的长度为1,则只返回包含此单个项目的叶节点。 (这是递归基础。)(O(1))
  2. 将预订单数组中的第一个条目存储为根节点。 (O(1))
  3. 在inorder数组中搜索该条目。 (O(n))的
  4. 将字符放在inorder数组中根节点的左侧,并将它们保存为char数组。从预订单数组中获取相同数量的字符(在根之后)。 (O(n)或O(1)当只是抛出指针/索引时。)
  5. 将字符放在根节点的右侧,并将它们保存为char数组。从预订单数组中获取相同数量的字符(在第一部分之后 - 应该只是剩余部分)。 (O(n)或O(1)当只是抛出指针/索引时。)
  6. 递归地从两个char数组中生成一个树。
  7. 从两个右边的char数组中递归生成一个树。
  8. 将两个树与您的根节点组合在一起。 (O(1)。)
  9. 非递归部分可以在O(n)中完成,并且对于每个递归级别对它们求和也是每个O(n)。因此总运行时间取决于递归级别的数量。如果你有一个近似平衡的树,深度是O(log n),因此我们得到O(n·log n)。由于唯一一个缓慢的部分是在inorder数组中搜索根节点,我想如果我们对树有更多的了解,我们可以优化它甚至更多。

    在最坏的情况下,我们在树中的每个节点都有一个递归级别,达到复杂度O(n·n)。

    示例:预订ABCDEF,Inorder FEDCBA,树:

                                       +---+
                                       | A |
                                       ++--+
                                        |
                                +---+   |
                                | B +<--+
                                ++--+
                                 |
                         +---+   |
                         | C +<--+
                         ++--+
                          |
                  +---+   |
                  | D +<--+
                  ++--+
                   |
           +---+   |
           | E +<--+
           ++--+
            |
    +---+   |
    | F +<--+
    +---+
    

答案 1 :(得分:0)

查看我的answer至此question。您可以通过在预订序列中添加节点来构建树,但是使用inorder位置作为比较器。

答案 2 :(得分:0)

你可以使用下面的代码,我刚刚写了同样的问题。它对我有用。

public class TreeFromInorderAndPreOrder {

public static List<Integer> inOrder = new ArrayList<Integer>();
public static List<Integer> preOrder = new ArrayList<Integer>();

public static void main(String[] args) {

    Node root = new Node();
    root.createRoot(5);
    for(int i = 0 ; i < 9 ; i++){
        if(i != 5){
            root.insert(i);
        }
    }

    inOrder(root);
    preOrder(root);
    for(Integer temp : inOrder){
        System.out.print(temp +  " ");
    }

    System.out.println();
    for(Integer temp : preOrder){
        System.out.print(temp + " ");
    }

    Node node1 = null;
    node1 = reConstructTree(root, (ArrayList<Integer>) inOrder, true);

    System.out.println();
    inOrder(node1);
    for(Integer temp : inOrder){
        System.out.print(temp +  " ");
    }

    System.out.println();

    for(Integer temp : preOrder){
        System.out.print(temp + " ");
    }

}

public static void inOrder(Node node){

    if(node!= null){
        inOrder(node.leftchild);
        inOrder.add(node.key);
        inOrder(node.rightChild);
    }

}

public static void preOrder(Node node){

    if(node != null){
        preOrder.add(node.key);
        preOrder(node.leftchild);
        preOrder(node.rightChild);
    }

}

public static Node reConstructTree(Node root, ArrayList<Integer> inOrder, 
    boolean  isLeft){

    if(preOrder.size() != 0 && inOrder.size() != 0){
        return null;
    }

    Node node = new Node();
    node.createRoot(preOrder.get(0));
    if(root != null && isLeft){
        root.leftchild = node;          
    }else if(root != null && !isLeft){
        root.rightChild = node;
    }
    int indx = inOrder.get(preOrder.get(0));
    preOrder.remove(0);
    List<Integer> leftInorder = getSublist(0, indx);
    reConstructTree(node, (ArrayList<Integer>) leftInorder, true);
    List<Integer> rightInorder = getSublist(indx+1, inOrder.size());
    reConstructTree(node, (ArrayList<Integer>)rightInorder, false);
    return node;

}

public static ArrayList<Integer> getSublist(int start, int end){
    ArrayList<Integer> list = new ArrayList<Integer>();
    for(int i = start ; i < end ; i++){
        list.add(inOrder.get(i));
    }

    return list;
}
}

答案 3 :(得分:0)

我在java中使用递归方法编写了一个使用分而治之法的示例程序

import java.util.LinkedList;
import java.util.Queue;

public class BinaryTreeNode {

private char data;
public char getData() {
    return data;
}
public void setData(char data) {
    this.data = data;
}
public BinaryTreeNode getLeft() {
    return left;
}
public void setLeft(BinaryTreeNode left) {
    this.left = left;
}
public BinaryTreeNode getRight() {
    return right;
}
public void setRight(BinaryTreeNode right) {
    this.right = right;
}
private BinaryTreeNode left;
private BinaryTreeNode right;

public static void levelTravesal(BinaryTreeNode node)
{
    Queue queue = new LinkedList();

    if(node == null)
        return;
    queue.offer(node);
    queue.offer(null);
    int level =0;
    while(!queue.isEmpty())
    {
        BinaryTreeNode temp = (BinaryTreeNode) queue.poll();

        if(temp == null)
        {
            System.out.println("Level: "+level);
            if(!queue.isEmpty())
                queue.offer(null);
            level++;
        }else {

        System.out.println(temp.data);

        if(temp.getLeft()!=null)
            queue.offer(temp.getLeft());

        if(temp.getRight()!=null)
            queue.offer(temp.getRight());
        }

    }
}

static int preIndex = 0;

public static void main(String[] args) {

    if(args.length < 2)
    {
        System.out.println("Usage: preorder inorder");
        return;
    }

    char[] preOrderSequence = args[0].toCharArray();
    char[] inOrderSequence = args[1].toCharArray();

    //char[] preOrderSequence = {'A','B','D','E','C','F'};
    //char[] inOrderSequence = "DBEAFC".toCharArray();

    if(preOrderSequence.length != inOrderSequence.length)
    {
        System.out.println("Pre-order and in-order sequences must be of same length");
        return;
    }

    BinaryTreeNode root = buildBinaryTree(preOrderSequence, inOrderSequence, 0, preOrderSequence.length-1);

    System.out.println();
    levelTravesal(root);


}

static BinaryTreeNode buildBinaryTree(char[] preOrder, char[] inOrder, int start, int end)
{
    if(start > end)
        return null;
    BinaryTreeNode rootNode = new BinaryTreeNode();
    rootNode.setData(preOrder[preIndex]);
    preIndex++;
    //System.out.println(rootNode.getData());
    if(start == end)
        return rootNode;
    int dataIndex = search(inOrder, start, end, rootNode.getData());
    if(dataIndex == -1)
        return null;
    //System.out.println("Left Bounds: "+start+" "+(dataIndex-1));
    rootNode.setLeft(buildBinaryTree(preOrder, inOrder, start, dataIndex - 1));
    //System.out.println("Right Bounds: "+(dataIndex+1)+" "+end);
    rootNode.setRight(buildBinaryTree(preOrder, inOrder, dataIndex+1, end));
    return rootNode;
}


static int search(char[] inOrder,int start,int end,char data)
{
    for(int i=start;i<=end;i++)
    {
        if(inOrder[i] == data)
            return i;
    }
    return -1;

}

}

答案 4 :(得分:0)

这是一种以非常简单的方式实现这一目标的数学方法:

使用的语言:Java

`
    / *     从给定的Inorder和Preorder遍历构造二叉树的算法。 以下是使用的术语:

i:代表提供的inorder数组

p:表示提供的预订单数组

beg1:inorder数组的起始索引

beg2:预编程数组的起始索引

end1:inorder数组的结束索引

end2:预编程数组的结束索引

* /

public static void constructTree(Node root,int [] i,int [] p,int beg1,int end1,int beg2,int end2)

{

if(beg1==end1 && beg2 == end2)
{
    root.data = i[beg1];
}
else if(beg1<=end1 && beg2<=end2)
{
    root.data = p[beg2];
    int mid = search(i, (int) root.data);
    root.left=new Node();
    root.right=new Node();
    constructTree(root.left, i, p, beg1, mid-1, beg2+1, beg2+mid-beg1);
    System.out.println("Printing root left : " + root.left.data);
    constructTree(root.right, i, p, mid+1, end1, beg2+1+mid-beg1, end2);
    System.out.println("Printing root left : " + root.right.data);
}

}

`

您需要通过以下代码调用该函数:

int[] i ={4,8,7,9,2,5,1,6,19,3,18,10}; //Inorder
int[] p ={1,2,4,7,8,9,5,3,6,19,10,18}; //Preorder
Node root1=new Node();
constructTree(root1, i, p, 0, i.length-1, 0, p.length-1);

如果您需要更详细的代码说明,请在评论中提及。我很乐意帮助:)。