打印二叉树中某节点的所有祖先节点

算法思路

二叉树的后序遍历顺序为左、右、根,递归写法为

postOrderTraversal(root->left);
postOrderTraversal(root->right);
cout<<root->val; 

递归的边界为

if(!root){
	return;
}

可以很清楚的看出递归栈的变化,即

树从根沿左子节点一直到叶子节点,沿途节点全部入栈,然后每次访问节点出栈后回溯到根节点,再将根节点的右子节点入栈重复上述入栈过程。

这样的话,对二叉树后序遍历找到特定的节点,此时栈中的所有节点即为该节点的祖先节点。

因此维护一个栈,显示地将递归过程中栈的变化模拟出来。

这里我们要注意后序遍历跟前中序的区别。由于前中序遍历根节点的访问都是在右子节点之前的,因此前中序遍历在访问子树根节点的右子节点时,根节点是直接出栈的。后序遍历的根节点的访问次序在最后,因此对于每棵子树根节点只有在以下两种情况才会出栈

  • 根节点无右子节点
  • 右子节点已经访问

因此要使用指针prev记录历史访问节点,以此来判断子树根节点的右子节点是否已经访问,即

root->right==nullptr || root->right == prev

算法代码

// 打印x节点的所有祖先节点
void PrintAncestor(TreeNode* root, int x) {
	stack<TreeNode*> stk;
    TreeNode* prev;
    while(root || !stk.empty()) {
        while(root && root->val != x) {
            stk.push(root);
            root = root->left;
        }
        if(root==nullptr) {  
            root = stk.top();
            stk.pop();
        }
        // 找到x后直接输出当前栈中所有节点算法结束
        if(root->val == x) {
            while(!stk.empty()) {
                cout<<stk.top()->val<<" ";
                stk.pop();
            }
			return;
        }
        if(root->right == nullptr || root->right == prev) {
            prev = root;
            root = nullptr;
        }
        else {
            stk.push(root);
            root = root->right;
        }
    }
}

ps:以上仅为个人理解,如有错误之处还请批评指正

你可能感兴趣的:(算法笔记,算法,数据结构,二叉树,c++)