Java 基于二叉树的线程二叉树实现

Java 基于二叉树的线程二叉树实现,java,tree,binary-tree,Java,Tree,Binary Tree,我正在为学校做作业。它主要由一个方法组成,该方法以二叉树作为输入,并返回一个双线程树。例如(如果left-child=null,那么left-child将与前面的inorder父级连接,如果right-child=null,它将链接到其inorder-successor。现在我对实现有了一个想法 我通过原始的二叉树进行递归迭代,并将顺序遍历存储到数组中。现在,因为我的教师实现要求线程树与二进制树是不同的类。我必须再次通过二叉树进行遍历,并将每个节点从binaryNode转换为threadedNo

我正在为学校做作业。它主要由一个方法组成,该方法以二叉树作为输入,并返回一个双线程树。例如(如果left-child=null,那么left-child将与前面的inorder父级连接,如果right-child=null,它将链接到其inorder-successor。现在我对实现有了一个想法

我通过原始的二叉树进行递归迭代,并将顺序遍历存储到数组中。现在,因为我的教师实现要求线程树与二进制树是不同的类。我必须再次通过二叉树进行遍历,并将每个节点从binaryNode转换为threadedNode,因此最后有一个“副本”初始二进制树的,但作为Threadedtree类型。执行此操作后,我将再次通过Threadedtree遍历,每当我看到空的左或右子级时,我将引用inorder arraylist并查找线程

正如你可能已经注意到的那样,这是非常低效的,我基本上遍历了树3次。我的教授说,这可以通过一次遍历递归完成,基本上转换为threadedNode并一次找到所有线程。我尝试了多种方法,但找不到一种有效的方法。有人这样做过吗有什么建议或者我能实现它的方法吗?谢谢

这是讲师指定的方法

public static <T> ThreadedNode<T> thread(BinaryNode<T> root)
{
   //threads a binary tree
}
publicstaticthreadednode线程(binarynoderoot)
{
//二叉树
}

您可以跳过方法中提到的第二次遍历。您可以动态地将节点从BinaryNode转换为ThreadedNode。我认为,对于inorder遍历,以及查找线程并将其转换为ThreadedTree,您仍然需要遍历两次

对于即时转换,您可以使用讲师提供的方法


HTH!

讲师是正确的。一次遍历就足够了

遍历原始二叉树,在遍历此树时创建新的
ThreadedNode
s

public static <T> ThreadedNode<T> thread(BinaryNode<T> root) {
    // We'll be keeping track of the "previous" node as we go, so use
    // a recursive helper method.  At first, there is no previous.
    return threadHelper(root, null);
}

private static <T> ThreadedNode<T> threadHelper(BinaryNode<T> n, ThreadedNode<T> previous) {

    // Create a new threaded node from the current root.  Note that the threaded nodes
    // are actually created in "preorder".  Assume the ThreadedNode constructor sets
    // the left, right, threadLeft, and threadRight fields to null.
    ThreadedNode<T> t = new ThreadedNode<T>(n.getData());

    // First go down the left side, if necessary.
    if (n.getLeft() != null) {
        // If there is a left child we have to descend.  Note that as we go down the
        // left side the previous doesn't change, until we start "backing up".
        t.left = threadHelper(n.getLeft(), previous);
        previous = t.left;
    } else {
        // If there is no left child, connect our left thread to the previous.
        t.threadLeft = previous;
    }

    // Now before we go down the right side, see if the previous
    // node (it will be in the left subtree) needs to point here.
    if (previous != null && previous.right == null) {
        previous.threadRight = t;
    }

    if (n.getRight() != null) {
        // If there is a right child we can descend the right.  As we go down we
        // update previous to the current node.  We do this just by passing the current
        // node as the second parameter.
        t.right = threadHelper(n.getRight(), t);
    } else {
        // No right child, no worries.  We'll hook up our thread-right pointer
        // later.
    }
    return t;
}
publicstaticthreadednode线程(binarynoderoot){
//我们将跟踪“上一个”节点,因此使用
//一个递归的助手方法。起初,没有以前的方法。
返回threadHelper(root,null);
}
私有静态ThreadedNode threadHelper(BinaryNode n,ThreadedNode previous){
//从当前根目录创建新的线程节点。请注意,线程节点
//实际上是在“预排序”中创建的。假设ThreadedNode构造函数集
//将left、right、threadLeft和threadRight字段设置为null。
ThreadedNode t=新的ThreadedNode(n.getData());
//如有必要,先从左边走。
如果(n.getLeft()!=null){
//如果有左撇子,我们必须下降。请注意,当我们下降时
//在我们开始“备份”之前,前面的左侧不会改变。
t、 left=threadHelper(n.getLeft(),上一个);
上一个=t.左;
}否则{
//如果没有左边的子线程,请将左边的线程连接到前面的子线程。
t、 threadLeft=上一个;
}
//现在,在我们走到右边之前,看看前面的
//节点(将在左子树中)需要指向此处。
if(previous!=null&&previous.right==null){
previous.threadRight=t;
}
如果(n.getRight()!=null){
//如果有一个合适的孩子,我们可以从右边往下走
//将上一个更新到当前节点。我们只通过传递当前
//节点作为第二个参数。
t、 right=threadHelper(n.getRight(),t);
}否则{
//没有合适的孩子,不用担心。我们将把我们的线程连接到正确的指针上
//稍后。
}
返回t;
}

以树为例(A(B(D)()C)。在按序遍历中,您命中的第一个节点是D。没有上一个节点。因此,将D另存为上一个。然后,您命中的下一个节点是B。上一个节点是D,没有右子节点,因此请添加一个从D到B的右线程指针。然后,将上一个设置为B并继续。下一个命中a的节点。B没有右子节点,因此,请添加一个从D到B的右线程链接m B到A。A有一个右子节点,因此继续,将previous设置为A。下一个节点是C。C没有左子节点,因此将C的线程左链接添加到previous的当前值,即A。

我考虑过这样做,但请记住,我还必须为访问的每个节点创建一个新的threadedNode,因为binaryNode和A之间存在差异d threadedNode。因此,我必须在按顺序遍历初始Binarytree时构建ThreadedTree。当然!在运行时发出线程化节点。如果您愿意,我可以更新我的答案。我了解您的实现,您的代码有一个小问题(右空子级似乎不线程化)但是现在我知道从哪里开始了。谢谢哦,对不起,我应该测试它。如果你卡住了,请让我知道。不过,很高兴这是一个起点。我想我已经完成了,我必须使用不同的树进行测试以确保。我求助于使用递归,但除了前一个元素的保持器之外,我还有一个堆栈,可以让我找到在递归调用结束之前删除下一个元素并将其附加到正确的子元素。非常感谢您的帮助。使用Gn。动态转换是什么意思?