给定一个中序线程二叉树和一个节点,如何找到该特定节点的父节点?

Posted

技术标签:

【中文标题】给定一个中序线程二叉树和一个节点,如何找到该特定节点的父节点?【英文标题】:Given an inorder threaded binary tree and a node, how to find the parent of that particular node? 【发布时间】:2021-11-24 06:43:22 【问题描述】:

我们得到一棵具有中序线程的二叉树。意思是,如果一个节点没有左孩子(右孩子),左线程(右线程)从那个节点链接到它的有序前驱(有序后继)。

你能帮我想出一个伪代码或算法来找到一个节点的父节点吗?例如(见下图),给定节点是 Q,父节点必须是 I。(我们是应该利用二进制是有序线程的给定想法)

TMI:我实际上需要这个伪代码/算法来创建另一个算法,该算法将获得二叉树的后继后继。

【问题讨论】:

为什么Q.left指向头节点?您的文字说它将指向 Q 的前身,但头节点 不是 Q 的前身。 图中的0和1是什么?你的节点有这些属性吗? @trincot 因为最左边的节点没有有序的前任,最右边的节点没有有序的后继,所以两个节点都指向头节点。 INORDER 遍历:Q U I C K S O R T @trincot 是的。最左边的属性称为 LTAG,最右边的属性称为 RTAG。基本上,如果它有一个左孩子(右孩子),则 LTAG (RTAG) 等于 1。否则为 0。 【参考方案1】:

从图片看来:

head 节点是一个特殊的哨兵节点,仅用作附加实际树的哨兵节点(可能为空) 节点有两个额外的布尔标志来指示它们是否有左/右子节点

那么查找给定节点的父节点的逻辑可以如下:

在给定节点的子树中找到最右边的节点。 按照该节点的右链接到祖先。我们知道原始节点在这个祖先节点的左子树中。 检查祖先的左孩子是否是原始节点。如果是这样,我们找到了父级。 去左边的孩子。我们知道原始节点必须在该节点下方的右侧路径上。找到它,并在到达那里之前归还我们必须拜访的父母。

这是该想法在 javascript 中的实现。这段代码 sn-p 定义了一个Node 类。它创建示例中给出的树。 Node 类有一个 inorder 迭代器,我们使用它来访问每个节点,然后使用上述算法显示其父节点:

class Node 
    constructor(value=null, left=null, right=null) 
        this.value = value;
        this.hasLeft = false;
        this.hasRight = false;
        this.left = left || this; // Default is self-reference
        this.right = right || this; // Default is self-reference
    
    insertLeft(value) 
        this.hasLeft = true;
        this.left = new Node(value, this.left, this);
        return this.left;
    
    insertRight(value) 
        this.hasRight = true;
        this.right = new Node(value, this, this.right);
        return this.right;
    
    parent() 
        // Find rightmost node of subtree
        let node = this;
        while (node.hasRight) 
            node = node.right;
        
        node = node.right; // go to ancestor
        // The this-node is in the left subtree of node.
        if (node.left === this) return node;
        node = node.left;
        while (node.right !== this) 
            node = node.right;
        
        return node;
    
    * inorder() 
        if (this.hasLeft) yield * this.left.inorder();
        if (this.right !== this) yield this; // When it is not the head
        if (this.hasRight) yield * this.right.inorder();
    


// Create the example tree:
let head = new Node(); // Sentinel node (without data)
head.insertLeft("C").insertLeft("I").insertLeft("Q").insertRight("U").right.right
                    .insertRight("S").insertLeft("K").right
                                     .insertRight("R").insertLeft("O").right
                                                      .insertRight("T");

// Visit each node, display its value and that of its parent:
for (let node of head.inorder()) 
    console.log("parent of " + node.value + " is " + node.parent().value);

【讨论】:

非常感谢! :)

以上是关于给定一个中序线程二叉树和一个节点,如何找到该特定节点的父节点?的主要内容,如果未能解决你的问题,请参考以下文章

⭐算法入门⭐《二叉树 - 二叉搜索树》简单09 —— LeetCode 285. 二叉搜索树中的中序后继

如何判定一颗树是完全二叉树和满二叉树

动画:面试算法之求二叉树的下一节点

使用特定方法拆分二叉树

2016搜狐笔试二叉树和最大的子树

面试题8:二叉树的下一个节点