输出二叉树中从每个叶子结点到根节点的路径

​ 该题目要求我们输出从每个叶子节点到根节点的路径,而我们只能从根节点遍历到叶子结点,这说明我们遍历的路径和题目要求的路径是逆序的,那么存储结点数据的容器必须遵循先进后出的规则,而我们发现栈就很好地符合这一标准,那就可以首先确定是要用栈来存储结点数据。
​ 首先不考虑如何输出从每个叶子节点到根节点的路径,简化下问题,我们先来考虑如何从根结点到一个叶子结点的问题,假设有一层数为h的二叉树,如何能走到该二叉树第h层的最左边的结点,这很简单,从根结点开始遍历,用栈存储路径上每个结点的数值,有左子树往左走,没有左子树再往右子树走,如果都没有左右子树说明到了叶子结点了,那么我们的路径就完整了,就可以打印栈的内容了,代码实现如下:

void RouteToRoot(BiTree root, SqStack* stack) {
    if (root) {
        stack_push(stack, root->data);//只要root不为空,就将root的值入栈
        if (!root->left_child&&!root->right_child)printStack(stack);
//当root没有左右孩子时,是叶子结点,此时叶子结点到根结点的路径已经完整
//则应打印栈的所有元素
        else { 
//当结点不是叶子结点时,先往左子树走
            RouteToRoot(root->left_child, stack); 
//再往右子树走
            RouteToRoot(root->right_child, stack);
        }
    }
}

​ 遍历一条路径是可以了,那么如何遍历该二叉树的所有路径呢?这不是很简单吗,遍历完一条路径后返回根节点再遍历一次,但是这样会出现一个新问题,如何确定我们当前遍历的路径不是之前已经遍历过的路径呢?这个问题有很多种办法解决,比如说存储遍历过的路径的数值,再将之与当前遍历的路径比较来确定,但这样会导致算法复杂度和空间复杂度很高,排除这种算法,如下图所示。

​ 1.假设我们遍历到了叶子结点d,此时这条路径便已经完整了,而结点b还有另一个右孩子结点e,那么遍历到d的路径和遍历到e的路径只差了最后一个结点,那么我们只需要把结点d出栈,再把结点e入栈,遍历到e的路径不就完整了吗,所以每次遍历到叶子结点我们将栈打印完后,只需将该叶子结点出栈。

​ 2.假设我们此时已经遍历完结点e并出栈了,此时b的左右孩子结点已经都遍历完了,不再被需要了,那么我们如何遍历到c结点呢,只需要将结点b出栈,那么a的左子树已经遍历完,此时再往右子树走,也就是c点走,这样我们就能获取遍历到c结点的路径。

​ 总结一下,结点出栈有两种情况,一是叶子结点且路径已被打印过,二是该结点的左右孩子结点都被遍历过了,下面代码实现。

  • 38
    点赞
  • 147
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值