Data structures 仅使用恒定额外空间的迭代线程二叉树遍历

Data structures 仅使用恒定额外空间的迭代线程二叉树遍历,data-structures,binary-tree,tree-traversal,non-recursive,Data Structures,Binary Tree,Tree Traversal,Non Recursive,如何在O(n)中非递归地遍历线程二叉树而不使用堆栈(只允许为临时变量使用常量额外空间,因此我们不能向树中的每个节点添加visit标志)。我花了很长时间考虑这个问题,但在我看来,除非我们要遍历包含树数据的内存位置,否则它是不可行的。假设我们使用多个数组表示来实现指针,那么我们就可以遍历O(n)中的树了,有人有其他想法吗 注意这是不是家庭作业,只是为了节省一些键盘笔划的能量来写关于家庭作业的评论 假设我们在C中有以下线程树表示: typedef结构线程二叉树{ int值; //指示right是指向正

如何在O(n)中非递归地遍历线程二叉树而不使用堆栈(只允许为临时变量使用常量额外空间,因此我们不能向树中的每个节点添加visit标志)。我花了很长时间考虑这个问题,但在我看来,除非我们要遍历包含树数据的内存位置,否则它是不可行的。假设我们使用多个数组表示来实现指针,那么我们就可以遍历O(n)中的树了,有人有其他想法吗


注意这是不是家庭作业,只是为了节省一些键盘笔划的能量来写关于家庭作业的评论

假设我们在C中有以下线程树表示:

typedef结构线程二叉树{
int值;
//指示right是指向正确的子项还是指向下一个子项的标志
//节点处于有序状态。
布尔右翼是孩子;
结构线程二叉树*左,*右;
}线程二叉树;
然后,在
O(1)
内存中遍历它可能如下所示:

void顺序(线程化的二叉树*节点)
{
线程化二叉树*prev=NULL;
//忽略空树
if(node==NULL)
返回;
//首先,到树最左边的叶子
while(节点->左!=NULL)
节点=节点->左;
while(节点!=NULL){
//沿着树的向上方向访问节点
printf(“%d\n”,节点->值);
prev=节点;
节点=节点->右侧;
如果(上一个->右\u是\u子项){
//我们正在下降到树上
如果(节点!=NULL){
//再次转到此子树中最左边的叶
while(节点->左!=NULL)
节点=节点->左;
}
}
//否则,我们会爬到树上
}
}

警告:我尚未运行此代码。

假设我们在C中有以下线程树表示:

typedef结构线程二叉树{
int值;
//指示right是指向正确的子项还是指向下一个子项的标志
//节点处于有序状态。
布尔右翼是孩子;
结构线程二叉树*左,*右;
}线程二叉树;
然后,在
O(1)
内存中遍历它可能如下所示:

void顺序(线程化的二叉树*节点)
{
线程化二叉树*prev=NULL;
//忽略空树
if(node==NULL)
返回;
//首先,到树最左边的叶子
while(节点->左!=NULL)
节点=节点->左;
while(节点!=NULL){
//沿着树的向上方向访问节点
printf(“%d\n”,节点->值);
prev=节点;
节点=节点->右侧;
如果(上一个->右\u是\u子项){
//我们正在下降到树上
如果(节点!=NULL){
//再次转到此子树中最左边的叶
while(节点->左!=NULL)
节点=节点->左;
}
}
//否则,我们会爬到树上
}
}

警告:我没有运行此代码。

这是用Java编写的代码:

public void inOrder() {
    Node<T> curr = root;
    boolean visited = false; //I haven't come across the node from which I came

    while (curr != null) {
        if (!visited && curr.left != null) { //Go to leftmost node
            curr = curr.left;
        } else {
            System.out.println(curr.head + " ");
            if (curr.right != null) { //I prioritize having childs than "threaded sons"
                curr = curr.right;
                visited = false;
            } else {
                curr = curr.rightThreaded;
                visited = true; //Means that I will come back to a node I've already looped, but now i'll print it, except if i'm at the last node
            }
        }
    }
}
public void inoorder(){
节点curr=根;
boolean visted=false;//我没有遇到我来自的节点
while(curr!=null){
如果(!visted&&curr.left!=null){//转到最左边的节点
当前=当前左侧;
}否则{
System.out.println(curr.head+“”);
如果(curr.right!=null){//我优先考虑孩子而不是“线程化的儿子”
curr=curr.right;
访问=假;
}否则{
curr=curr.right;
visited=true;//表示我将返回到已循环的节点,但现在我将打印它,除非我在最后一个节点
}
}
}
}
节点是ThreadedBinaryTree的内部类:

private static class Node<T> {
    private T head;
    private Node<T> left;
    private Node<T> right;
    private Node<T> leftThreaded;
    private Node<T> rightThreaded;

    public Node(T head, Node<T> leftThreaded, Node<T> rightThreaded) {
        this.head = head;
        this.leftThreaded = leftThreaded;
        this.rightThreaded = rightThreaded;
    }
}
私有静态类节点{
私人T型头;
私有节点左;
私有节点权;
私有节点左线程;
私有节点;
公共节点(T头、节点左线程、节点右线程){
这个头=头;
this.leftThreaded=leftThreaded;
this.rightThreaded=rightThreaded;
}
}

这是用Java编写的代码:

public void inOrder() {
    Node<T> curr = root;
    boolean visited = false; //I haven't come across the node from which I came

    while (curr != null) {
        if (!visited && curr.left != null) { //Go to leftmost node
            curr = curr.left;
        } else {
            System.out.println(curr.head + " ");
            if (curr.right != null) { //I prioritize having childs than "threaded sons"
                curr = curr.right;
                visited = false;
            } else {
                curr = curr.rightThreaded;
                visited = true; //Means that I will come back to a node I've already looped, but now i'll print it, except if i'm at the last node
            }
        }
    }
}
public void inoorder(){
节点curr=根;
boolean visted=false;//我没有遇到我来自的节点
while(curr!=null){
如果(!visted&&curr.left!=null){//转到最左边的节点
当前=当前左侧;
}否则{
System.out.println(curr.head+“”);
如果(curr.right!=null){//我优先考虑孩子而不是“线程化的儿子”
curr=curr.right;
访问=假;
}否则{
curr=curr.right;
visited=true;//表示我将返回到已循环的节点,但现在我将打印它,除非我在最后一个节点
}
}
}
}
节点是ThreadedBinaryTree的内部类:

private static class Node<T> {
    private T head;
    private Node<T> left;
    private Node<T> right;
    private Node<T> leftThreaded;
    private Node<T> rightThreaded;

    public Node(T head, Node<T> leftThreaded, Node<T> rightThreaded) {
        this.head = head;
        this.leftThreaded = leftThreaded;
        this.rightThreaded = rightThreaded;
    }
}
私有静态类节点{
私人T型头;
私有节点左;
私有节点权;
私有节点左线程;
私有节点;
公共节点(T头、节点左线程、节点右线程){
这个头=头;
this.leftThreaded=leftThreaded;
this.rightThreaded=rightThreaded;
}
}

你看过了吗?@svick算法的第二步是第二步:将左边的子节点放在已访问节点列表中,并将其作为当前节点考虑。转到步骤6。我在问题中提到,我需要不断增加额外的空间,我的答案与你的问题相关吗?如果是,请将其标记为一。如果没有,请告诉我原因,我会尝试改进它。你看了吗?@svick第二步