有一棵二叉树,如下图所示:

其中 # 表示空结点。

先序遍历:A B D E G C F

问题:怎么得到从根结点到任意结点的路径呢?

示例:输入 G,怎么得到从结点 A 到结点 G 的路径呢?

很明显,我们一眼就能看出来路径是 A B E G。如何通过程序得到这条路径就是我们接下来需要做的。

定义二叉树的 链式存储结构 如下:

typedef struct BiTNode {
char data;
struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;// 二叉树结点的存储结构

二叉树的遍历有三种方式:即先序遍历,中序遍历,后序遍历。

先序遍历是先访问结点再递归子树。我们只需要访问到目标结点的时候就知道了路径就可以结束递归,因此正好符合要求。另外两个也可以得到路径,但是还要先访问子树,显然是没必要的。

先序遍历可以通过递归实现,我们只需要加个容器来保存路径即可。 正好满足要求。由于不知道路径的长度,因此采用 链栈 来实现。

链栈 结构如下:

typedef struct StackNode {
char data;
struct StackNode* next;
}StackNode, * Stack;// 链栈

完整代码:

/*************************************************************************
实现功能: 输出从根结点到指定结点的路径
编译环境: Visual Studio 2019
更新日期: 2019年10月10日15:16:28
更新内容: 增加清空二叉树和栈的函数
优化if判断条件
博客链接: https://blog.csdn.net/pfdvnah/article/details/102387839
作者: wowpH
*************************************************************************/ #define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h>// exit,malloc,free头文件 #define EMPTY_NODE '#'
#define TRUE 1
#define FALSE 0
#define STACK_EMPTY TRUE
#define STACK_NOT_EMPTY FALSE
#define FOUND TRUE
#define NOT_FOUND FALSE typedef struct BiTNode {
char data;
struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;// 二叉链表 typedef struct StackNode {
char data;
struct StackNode* next;
}StackNode, * Stack;// 链栈 // 创建二叉树结点,返回创建的二叉树结点
BiTree createBiTNode();
// 创建二叉树,返回根结点
BiTree createBiTree();
// 初始化二叉树,返回根结点
BiTree initBiTree();
// 清空二叉树
void clearBiTree(BiTree T); // 创建栈结点,返回创建的栈结点
Stack createStackNode();
// 初始化栈,返回栈的头结点
Stack initStack();
// 栈是否初始化
int isStackExist(Stack S);
// 栈是否为空
int isStackEmpty(Stack S);
// 入栈
char push(Stack S, char data);
// 出栈
char pop(Stack S);
// 查看栈顶元素
char peek(Stack S);
// 清空栈
void clearStack(Stack S); // 寻找路径,返回是否找到目标结点
int searchPath(BiTree T, Stack S);
// 是否找到目标结点
int isFindTargetNode(Stack S);
// 显示路径
void showPath(Stack S);
// 输出路径
void outputPath(Stack S); // 输出程序提示信息
void outputTips(); int main() {
outputTips();// 输出程序提示信息
BiTree tree = initBiTree();
Stack stack = initStack();// 头结点存储目标结点信息
searchPath(tree, stack);// 寻找路径
showPath(stack);// 输出路径信息
clearBiTree(tree);// 清空二叉树
clearStack(stack);// 清空栈
return 0;
} /******************************** 二叉树 ********************************/
// 创建二叉树结点
BiTree createBiTNode() {
BiTree newNode = (BiTree)malloc(sizeof(BiTNode));
if (newNode == NULL) {
printf("错误(%d):创建二叉树结点错误!\n", __LINE__);
exit(0);
}
newNode->lchild = NULL;
newNode->rchild = NULL;
return newNode;
} // 创建二叉树
BiTree createBiTree() {
char ch = getchar();
if (ch != '\n' && ch != EMPTY_NODE) {
BiTree T = createBiTNode();
T->data = ch;
T->lchild = createBiTree();// 左子树
T->rchild = createBiTree();// 右子树
return T;
}
return NULL;
} // 初始化二叉树
BiTree initBiTree() {
printf("输入二叉树:");
BiTree tree = createBiTree();
char enter = getchar();
return tree;
} // 清空二叉树
void clearBiTree(BiTree T) {
if (T != NULL) {
clearBiTree(T->lchild);
clearBiTree(T->rchild);
free(T);
}
} /********************************** 栈 **********************************/
// 创建栈结点
Stack createStackNode() {
Stack newNode = (Stack)malloc(sizeof(StackNode));
if (newNode == NULL) {
printf("错误(%d):创建栈结点错误!\n", __LINE__);
exit(0);
}
newNode->next = NULL;
return newNode;
} // 初始化栈,并返回头结点
Stack initStack() {
printf("输入指定结点:");
char targetNode = getchar();
Stack stack = createStackNode();// 头结点存储目标结点数据
stack->data = targetNode;
return stack;
} // 栈头结点是否存在
int isStackExist(Stack S) {
if (S == NULL) {
printf("错误(%d):栈的头结点未初始化!\n", __LINE__);
exit(0);
}
return TRUE;
} // 栈是否为空
int isStackEmpty(Stack S) {
if (isStackExist(S) == FALSE) {
return STACK_EMPTY;
}
if (S->next == NULL) {
return STACK_EMPTY;
}
return STACK_NOT_EMPTY;
} // 入栈,data是要入栈的结点的数据
char push(Stack S, char data) {
if (isStackExist(S) == TRUE) {
Stack node = createStackNode();
node->data = data;
node->next = S->next;
S->next = node;
}
return data;
} // 出栈,返回栈顶结点的数据
char pop(Stack S) {
char ret = STACK_EMPTY;
if (isStackEmpty(S) == STACK_NOT_EMPTY) {
Stack delete = S->next;
S->next = delete->next;
ret = delete->data;
free(delete);
}
return ret;
} // 查看栈顶元素
char peek(Stack S) {
return isStackEmpty(S) == STACK_EMPTY ? STACK_EMPTY : S->next->data;
} // 清空栈
void clearStack(Stack S) {
while (isStackEmpty(S) == STACK_NOT_EMPTY) {
pop(S);
}
free(S);
} /********************************* 路径 *********************************/
// 寻找路径
int searchPath(BiTree T, Stack S) {
if (isFindTargetNode(S) == FOUND) {
return FOUND;
}
if (T == NULL) {// 空树
return NOT_FOUND;
}
push(S, T->data);
// 查找子树
if (searchPath(T->lchild, S) == FOUND) {
return FOUND;
}
if (searchPath(T->rchild, S) == FOUND) {
return FOUND;
}
pop(S);
return NOT_FOUND;
} // 是否找到目标结点
int isFindTargetNode(Stack S) {
if (isStackEmpty(S) == STACK_NOT_EMPTY && peek(S) == S->data) {
return FOUND;
}
return NOT_FOUND;
} // 输出路径,递归
void outputPath(Stack S) {
if (isStackEmpty(S) == STACK_NOT_EMPTY) {
outputPath(S->next);
if (isStackEmpty(S->next) == STACK_NOT_EMPTY) {
printf(" ");
}
printf("%c", S->next->data);
}
} // 显示路径
void showPath(Stack S) {
if (isFindTargetNode(S) == FOUND) {
printf("路径:");
outputPath(S);
printf("\n");
} else {
printf("未找到结点'%c'\n", S->data);
}
} // 输出提示
void outputTips() {
printf("1、先序输入二叉树\n");
printf("2、空结点用'%c'表示\n", EMPTY_NODE);
printf("3、Enter表示输入结束\n");
printf("4、字符个数必须正确\n");
} /*************************************************************************
1、先序输入二叉树
2、空结点用'#'表示
3、Enter表示输入结束
4、字符个数必须正确 示例1:
输入二叉树:ABD##EG###CF###
输入指定结点:G
路径:A B E G 示例2:
输入二叉树:124##56##7##3##
输入指定结点:7
路径:1 2 5 7
*************************************************************************/

二叉树根结点到任意结点的路径(C语言)的更多相关文章

  1. 【Leetcode】查找二叉树中任意结点的最近公共祖先(LCA问题)

    寻找最近公共祖先,示例如下: 1 /           \ 2           3 /    \        /    \ 4    5      6    7 /    \          ...

  2. [二叉树-根到叶的子路径]路径总和 III (两层递归)

    题目437. 路径总和 III 给定一个二叉树,它的每个结点都存放着一个整数值. 找出路径和等于给定数值的路径总数. 路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父 ...

  3. 求二叉树中第K层结点的个数

    一,问题描述 构建一棵二叉树(不一定是二叉查找树),求出该二叉树中第K层中的结点个数(根结点为第0层) 二,二叉树的构建 定义一个BinaryTree类来表示二叉树,二叉树BinaryTree 又是由 ...

  4. Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)——无非是在传统遍历过程中修改叶子结点加入后继结点信息(传统是stack记录),然后再删除恢复

    先看看线索二叉树 n个结点的二叉链表中含有n+1(2n-(n-1)=n+1)个空指针域.利用二叉链表中的空指针域,存放指向结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索 ...

  5. [LeetCode] Closest Leaf in a Binary Tree 二叉树中最近的叶结点

    Given a binary tree where every node has a unique value, and a target key k, find the value of the n ...

  6. PTA 统计二叉树度为2的结点个数

    6-4 统计二叉树度为2的结点个数 (11 分)   本题要求实现一个函数,可统计二叉树中度为2的结点个数. 函数接口定义: int NodeCount ( BiTree T); T是二叉树树根指针, ...

  7. PTA 统计二叉树度为1的结点个数

    6-3 统计二叉树度为1的结点个数 (10 分)   本题要求实现一个函数,可统计二叉树中度为1的结点个数. 函数接口定义: int NodeCount ( BiTree T); T是二叉树树根指针, ...

  8. 剑指Offer面试题:23.二叉树中和为某一值的路径

    一.题目:二叉树中和为某一值的路径 题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.例如输入下图中二叉树和整数2 ...

  9. P143、面试题25:二叉树中和为某一值的路径

    题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.二叉树结点的定义如下:struct BinaryTreeNode ...

随机推荐

  1. Linux(Contos7)下使用SSH远程安装MySQL 8.0.17 完整笔记

    1. 使用putty 配置远程服务器连接,登录服务器. 由于没有指定下载包 使用 yum install mysql-server  提示 未指定包,如: 2. 因为甲骨文的收购了Mysql并且对My ...

  2. 避免MySQL出现重复数据处理方法

    对于常规的MySQL数据表中可能存在重复的数据,有些情况是允许重复数据的存在,有些情况是不允许的,这个时候我们就需要查找并删除这些重复数据,以下是具体的处理方法! 方法一:防止表中出现重复数据 当表中 ...

  3. Kubernetes中如何让Deployment更新镜像

    问题描述 我的deployment有单个pod,我的自定义docker镜像如下: 123 containers: - name: mycontainer image: myimage:latest 在 ...

  4. Java 整数间的除法运算如何保留所有小数位?

      1.情景展示 double d = 1/10; System.out.println(d); 返回的结果居然是0.0!这是怎么回事儿? 2.原因分析 第一步:你会发现用运算结果也可以用int类型接 ...

  5. 2018ECNA Difference[时空复杂度]

    目录 题干 代码和解释 题干 代码和解释 本题给出一个数列的第一个数A(1),要求找出m第一次出现(直接出现在数列中或是数列中某两项的差的绝对值)在这个数列的第几步中.数列递推公式:A(n+1)=A( ...

  6. 【转】vim复制与粘贴

    用vim写代码时,经常遇到这样的场景,复制多行,然后粘贴. 这样做:1. 将光标移动到要复制的文本开始的地方,按v进入可视模式.2. 将光标移动到要复制的文本的结束的地方,按y复制.此时vim会自动将 ...

  7. [Beta]Scrum Meeting#5

    github 本次会议项目由PM召开,时间为5月10日晚上10点30分 时长15分钟 任务表格 人员 昨日工作 下一步工作 木鬼 撰写博客整理文档 撰写博客整理文档 swoip 改进界面 改进界面 b ...

  8. OpenStack创建网络和虚拟机、dhcp设备、虚拟路由器、虚拟机访问外网原理分析

    创建网络和虚拟机流程: 1.创建网络和子网 背后发生了什么: Neutron让控制节点上针对此子网的dhcp(虚拟设备)启动,用于给该子网下的实例分配ip 2.生成虚拟机 背后发生了什么: 用户通过G ...

  9. T-MAX——团队展示

    第一次团队博客:百战黄沙穿金甲 基础介绍 这个作业属于哪个课程 2019秋福大软件工程实践Z班 这个作业要求在哪里 团队作业第一次-团队展示 团队名称 T-MAX 这个作业的目标 展现团队成员的风采, ...

  10. phpstudy(小皮面板)和phpstudy2018 配置php的区别

    phpstudy(小皮面板)和phpstudy2018 配置php的区别 一.总结 一句话总结: phpstudy(小皮面板) 和 phpstudy2018 只是引入的php的位置不同,但是核心代码还 ...