首页 > 编程语言 >【数据结构与算法】输出二叉树中从每个叶子结点到根结点的路径 C++实现(二叉树+栈+深度优先搜索)

【数据结构与算法】输出二叉树中从每个叶子结点到根结点的路径 C++实现(二叉树+栈+深度优先搜索)

时间:2024-08-10 13:52:35浏览次数:15  
标签:结点 遍历 int C++ stk 叶子 二叉树 节点

二叉树叶子节点到根节点的路径

题目描述

给定一棵二叉树的后序遍历序列 post[s1..t1] 和中序遍历序列 in[s2..t2],设计一个算法,输出二叉树中从每个叶子节点到根节点的路径。请使用栈的数据结构解决。

输入格式

输入包括两行:

  • 第一行为后序遍历序列 post[s1..t1]
  • 第二行为中序遍历序列 in[s2..t2]

保证构成一棵唯一的二叉树。

输出格式

输出多行,每行表示一条从叶子节点到根节点的路径,路径上的节点按照从叶子节点到根节点的顺序排列。

样例 #1

样例输入 #1

DEBGFCA
DBEAFGC

样例输出 #1

ABD
ABE
ACFG

提示

首先,后序遍历的最后一个元素是树的根。然后,你可以在中序遍历序列中找到这个根,这样就可以确定哪些元素在左子树,哪些在右子树。然后,你可以递归地构造左子树和右子树。

利用栈的特性,可以方便地实现从叶子节点到根节点的路径的输出。在遍历过程中,将路径上的节点压入栈中,当遍历到叶子节点时,就可以将栈中的元素按照出栈顺序输出,即得到从叶子节点到根节点的路径。


思路

先检查传入的二叉树 T 是否存在。如果存在,就将当前节点的数据 T->data 压入栈 stk。这是因为栈的特性决定了它能够保存从叶子节点到根节点的路径。

接着,检查当前节点是否是叶子节点,即它的左右子树 T->leftT->right 是否都不存在。如果是叶子节点,就输出从栈底到栈顶的所有元素,即从根节点到当前叶子节点的路径,然后从栈中弹出当前节点。

如果当前节点不是叶子节点,就递归地对左子树 T->left 和右子树 T->right 调用 findPath。这样,就可以遍历到所有的叶子节点。

最后,无论当前节点是否是叶子节点,都会在遍历完其所有子树后从栈中弹出当前节点。这是因为在返回到父节点之前,需要清理当前节点的信息,否则会影响其他路径的输出。

算法分析

对于时间复杂度,算法需要遍历二叉树的所有节点,所以时间复杂度为 O ( n ) O(n) O(n),其中 n n n 是二叉树的节点数。空间复杂度主要取决于栈的大小和递归深度,最坏情况下,当二叉树退化为链表时,空间复杂度为 O ( n ) O(n) O(n)。


AC代码

#include <algorithm>
#include <cstring>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
using Status = int;
using ElemType = char;

const int N = 1e4 + 7;
const int TRUE = 1;
const int FALSE = 0;
const int OK = 1;
const int ERROR = 0;
const int INFEASIBLE = -1;
// const int OVERFLOW = -2;

int n;
ElemType a[N];

struct TreeNode {
	ElemType data;
	struct TreeNode *left, *right;
};
using BiTree = TreeNode *;

struct Stack {
	ElemType data[N];
	int top;
};

BiTree createBiTree(char *last, char *mid, int len) {
	if (len <= 0) {
		return NULL;
	}
	// 后序序列最后一个节点为根节点
	char root = last[len - 1];
	// 中序序列中找根节点
	int index = 0;
	while (mid[index] != root) {
		index++;
	}

	// 创建根节点
	BiTree T = (TreeNode *)malloc(sizeof(TreeNode));

	T->data = root;
	T->left = createBiTree(last, mid, index);
	T->right = createBiTree(last + index, mid + index + 1, len - index - 1);
	return T;
}

Status initStack(Stack &stk) {
	stk.top = 0;
	return OK;
}

Status push(Stack &stk, ElemType e) {
	if (stk.top >= N) {
		return ERROR;
	}
	stk.data[++stk.top] = e;
	return OK;
}

Status pop(Stack &stk) {
	if (!stk.top) {
		return ERROR;
	}
	stk.top--;
	return OK;
}

ElemType getTop(Stack stk) { return stk.data[stk.top]; }

void findPath(BiTree T, Stack &stk) {
	if (T) {
		push(stk, T->data);
		if (!T->left && !T->right) {
			for (int i = 1; i <= stk.top; i++) {
				cout << stk.data[i];
			}
			cout << endl;
			pop(stk);
			return;
		}
		findPath(T->left, stk);
		findPath(T->right, stk);
		pop(stk);
	}
}

int main() {
	char post[N], in[N];
	cin >> post >> in;

	BiTree T = createBiTree(post, in, strlen(post));
	Stack stk;
	initStack(stk);

	findPath(T, stk);
	return 0;
}

标签:结点,遍历,int,C++,stk,叶子,二叉树,节点
From: https://blog.csdn.net/qq_34988204/article/details/138277694

相关文章

  • 二叉树的学习
    目录树形结构树中的概念树的表示方法二叉树二叉树的重要性质二叉树的存储遍历中序遍历后续遍历层序遍历创建二叉树二叉树的遍历获取树中节点个数获取叶子节点的个数获取第k层节点个数获取二叉树的高度检测val元素是否存在二叉树相关题目检查两棵树是否相......
  • C++类和对象(上)
    文章目录一、类的定义1、类的定义格式2、访问限定符3、类域二、实例化1、实例化概念2、对象的大小三、this指针一、类的定义1、类的定义格式calss是定义类的关键词,用法更C语言中的结构体struct关键词用法一样,区别是类可以在里面创建函数,当然在C++中也是兼容结......
  • C++day05
    1>思维导图2>搭建一个货币的场景,创建一个名为RMB的类,该类具有整型私有成员变量yuan(元)、jiao(角)和fen(分),并且具有以下功能:(1)重载算术运算符+和-,使得可以对两个RMB对象进行加法和减法运算,并返回一个新的RMB对象作为结果。(2)重载关系运算符>,判断一个RMB对象是......
  • C++day04
    1】思维导图2】完成关系运算符重载,实现成员函数和全局函数的版本。#include<iostream>usingnamespacestd;classStu{friendbooloperator<(constStu&L,constStu&R);private:intage;intid;public:Stu(){}Stu(intage,intid):age(age)......
  • C++day03
    1>思维导图2>设计一个Per类,类中包含私有成员:姓名、年龄、指针成员身高、体重,再设计一个Stu类,类中包含私有成员:成绩、Per类对象p1,设计这两个类的构造函数、析构函数和拷贝构造函数。#include<iostream>usingnamespacestd;classPer{private:stringname;......
  • C++ int32, int64 和十六进制字符串的转换
       #include<iostream>#include<string>#include<cstring>//用于memset,strlen#include<algorithm>/***@brife:将一个int64数字转为十六进制字符串*@note:int64Value:0,hexStr:0000000000000000int64Value:-1,h......
  • C++ 11 auto(自动类型推导) 和 decltype(获取表达式类型)
    C++(2)auto占位符自动类型推导auto能够实现类型的自我推导,并不代表一个实际的类型声明。auto只是一个类型声明的占位符。auto声明的变量,必须马上初始化,以让编译器推断出它的实际类型,并在编译时将auto占位符替换为真正的类型。注意:C++11中auto不能用于函......
  • 二叉树——6.平衡二叉树
    力扣题目链接给定一个二叉树,判断它是否是高度平衡的二叉树。示例:TureFalse首先做这道题目前要明白什么是平衡二叉树?平衡二叉树的定义是,对于二叉树的每一个节点,它的左子树和右子树的高度差不超过1。结合示例中的两个例子理解平衡二叉树的定义。完整代码如下:#Definition......
  • 【C++】decltype
    1、简介我们之前使用的typeid运算符来查询一个变量的类型,这种类型查询在运行时进行。RTTI机制为每一个类型产生一个type_info类型的数据,而typeid查询返回的变量相应type_info数据,通过name成员函数返回类型的名称。同时在C++11中typeid还提供了hash_code这个成员函数,用于返回类型......
  • C++入门基础知识(笔记):成员变量和成员函数分开存储,非静态成员变量,是属于类的对象上,空对
    在C++中,类内的成员变量和成员函数分开存储只有非静态成员变量才属于类的对象上。1.空对象占用内存空间为:1个字节,代码演示:#include<iostream>usingnamespacestd;//成员变量和成员函数分开存储classPerson{};//这是一个空对象voidtest01(){ Personp;......