当前位置: 首页 > 知识库问答 >
问题:

不使用额外内存的级别顺序树遍历

晏晨朗
2023-03-14

我知道树的水平顺序遍历的算法。(我想大家都知道)该算法使用队列存储树的节点。有没有不使用额外内存的算法?该算法不能使用递归(这样我们就可以使用堆栈)。注意,该树以左子右同级表示形式给出。不允许使用其他指针
对于树,C中的结构是:

struct node {
int data;
struct node *left-child;
struct node *right-sibling;
}

树用指向根节点的指针表示。当然,root不能有正确的兄弟。

共有3个答案

羊舌源
2023-03-14

如果要在恒定空间中遍历树,可以应用莫里斯级顺序遍历。你可以参考这里和这里。

酆翔宇
2023-03-14

如果可以在树的每个节点中存储一个额外的下一个指针,该指针按每个级别的级别顺序指向下一个节点,则可以在常量空间中执行级别顺序遍历。

左丘嘉言
2023-03-14

一种方法是使用空的右同级指针使所有节点成为彼此的同级(暂时)。

你可以用一个又慢又快的指针。最快的一个总是在最后一个同级(它的空指针为右同级)。然后,慢速节点的左子节点指针将被复制到该右同级节点,之后快速指针将再次运行到末端。慢速指针向右移动一步,重复相同的操作。当慢速指针也到达终点时,所有节点都将是同级节点。可以使用慢速或快速指针按级别顺序输出值。这将完成任务,但树将因此被摧毁。

要恢复树,我建议在上述过程中,所有兄弟边的方向都是反向的。这意味着您需要另一个落后于慢速指针的指针。这将允许在这两者之间执行反转。这有点晦涩,因为右同胞实际上会指向一些主要是左同胞的东西。

在上面的过程之后,指针将位于节点列表的末尾,但是由于我们已经反转了同级边,所以我们也可以返回并再次反转边。一个困难是知道哪些同级指针应该再次变为null(当节点最初是最右边的子节点时)。这可以通过再次让一个快速指针向前移动(向左)来查找具有子节点的节点来实现。如果落后于慢指针的指针命中这样一个子指针,我们知道慢指针的节点应该得到一个空指针,即右同级。当应用此修复程序时,快速指针应再次向前运行以查找另一个父节点。。。等

请注意,此算法不会更改左子指针。

所以,总的来说,这个解决方案使用了三个指针和树本身的结构。

下面是我在以下实现中使用的示例树:

          1
         /
        2 ------------ 3 ---------4
       /              /          /
      5 -- 6 -- 7    8 -- 9     10 -- 11 -- 12 -- 13
          /                           /
        14 -- 15 -- 16              17 -- 18 -- 19

JavaScript中的实现--可运行代码段:

function * traverse(node) {
    let lead = node; // ...walks somewhere ahead of node
    let lag = null; // ... always follows one step behind node
    while (node) {
        yield node.data; // output
        lead.rightSibling = node.leftChild;
        while (lead.rightSibling) lead = lead.rightSibling;
        // rotate: point node to next right-sibling, and reverse direction of sibling edge
        [node.rightSibling, lag, node] = [lag, node, node.rightSibling]
    }
    
    // Restore tree
    lead = node = lag.rightSibling; // backwards
    lag.rightSibling = null;
    while (lead !== null && lead.leftChild === null) lead = lead.rightSibling; // actually going left!
    while (node) {
        if (lead !== null && lead.leftChild === lag) {
            // When lag is the leftChild of some node (lead), then lag should not be the target of a rightSibling
            [node.rightSibling, lag, node] = [null, node, node.rightSibling];
            // Find previous parent
            lead = lead.rightSibling;
            while (lead !== null && lead.leftChild === null) lead = lead.rightSibling; // actually going left!
        } else {
            // walk back and restore sibling pointers
            [node.rightSibling, lag, node] = [lag, node, node.rightSibling];
        }
    }
}

// Create node, given its data and child nodes
function Node(data, ...children) {
    // Link the children as siblings
    if (children.length > 1) children.reduceRight((a, b) => (b.rightSibling = a, b))
    // Create the node itself. For now, without any siblings
    return {
        data,
        leftChild: children.length ? children[0] : null,
        rightSibling: null
    };
}

// Example tree
let tree = Node(1, 
    Node(2, 
        Node(5), Node(6,
            Node(14), Node(15), Node(16)
        ), Node(7)
    ), Node(3,
        Node(8), Node(9)
    ), Node(4,
        Node(10), Node(11,
            Node(17), Node(18), Node(19)
        ), Node(12), Node(13)
    )
);

// Apply the algorithm and output the yielded values     
console.log(...traverse(tree)); 

 类似资料:
  • 我想逐级显示树结构。我当前的代码执行BFS或级别顺序遍历,但我无法使输出像树一样显示树结构。请参阅当前输出和预期输出。 我的想法是使用某种计数来迭代队列中同一级别的元素。 我怎么能这样做呢。 没有此功能的原始代码可以在下面的链接中找到,以防有人需要整个实现,否则只需查看下面的显示BFS功能。 java中泛型树(n元树)的级顺序遍历 谢谢 另外,我之前发布了一个具有相同功能的逻辑问题,因为已经回答了

  • 我正在尝试编写一个函数,该函数将使用级别顺序遍历将一个元素插入到二叉树中。我的代码遇到的问题是,当我在树中插入一个新节点后打印级别顺序遍历时,它以无限循环的方式打印元素。1,2,3,4,5,6,7,8这个数字一直在飞驰过终点站。我将感谢任何关于如何补救这种情况的指示和建议。 这是我通过修改级别顺序遍历技术将一个元素插入到树中的地方 主

  • 这是一个leetcode问题。 给定一个二叉树,返回其节点值的级序遍历(即从左到右,逐级)。 例如:给定二叉树, 将其级别顺序遍历返回为: 但我正在用JavaScript尝试一种新的方式,而不是完全按照他们的解决方案。到目前为止,我能够打印阵列,但 如何在新行中打印不同的级别 以下是我目前的代码: 输入:[3,9,20,空,空,15,7], LeetCode问题链接:BinarytreeTrave

  • (为了避免冗长的解释,我所要寻找的只是java中泛型树(n元树)的级别顺序遍历。提供的代码正常工作,需要级别顺序显示功能。环顾四周一个小时,但找不到通用n元树的参考。如果soemone能帮助我在代码上构建LevelOrderDisplay函数,我将不胜感激,因为它将帮助我理解我遇到的队列错误。谢谢 我一直在尝试在工作中实现Autosys作业计划的树表示。由于每个作业(流程)可以有一个或多个依赖作业

  • 我正在尝试对二叉树进行级别顺序遍历。但诀窍是代替正常的级别顺序遍历,我想做另一种选择。对于例如。 普通等级顺序遍历 : 我要找的是我们打印根。现在,对于每一个偶数级,我都想逆时针旋转,对于每奇数级,都会顺时针旋转: 对于这种遍历,输出应该是: 这是我到目前为止尝试的,但这产生的输出与我试图实现的输出略有不同: 该程序产生以下输出: < code>1 3 2 5 4 7 6 10 11 9 8 我需

  • 我必须创建两个类:NonBinaryTree和SingleNode类,包含一些处理节点和整个树的方法(在NonBinaryTree类中)。我在使用队列(先进先出类型)实现非二叉树的BFS(层次顺序)遍历时遇到过问题。由于二叉树有很多资源,每个节点最多有两个子节点,我还没有找到任何可以帮助我解决非二叉树问题的资源。 到目前为止,我做了这个代码: 我的树: 在此处输入图像描述 我需要按以下顺序处理节点