我正在做一个关于从预订和顺序遍历构建二叉树的任务(每个节点中的一个字符),我试图将我的大脑包围在如何构建实际树。
以下是关于如何实现这一目标的思考过程:
我已经完成了步骤1-4,但我不太确定如何正确构建我的树,并且想知道是否有人有任何指针。谢谢。
答案 0 :(得分:5)
在构建新树之前进行递归。所以,你的清单看起来像这样:
非递归部分可以在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)
答案 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);
如果您需要更详细的代码说明,请在评论中提及。我很乐意帮助:)。