二叉树根结点到任意结点的路径(C语言)

二叉树示例

二叉树

其中 # 表示空结点。

先序遍历:ABD##EG###CF###
中序遍历:#D#B#G#E#A#F#C#
后序遍历:##D##G#EB##F#CA


问题

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

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

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


存储结构

采用 链式存储结构 来保存二叉树的信息,结构如下:

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);

函数定义

有点多,不单独列出,参见完整代码。

知识点

本文作为一篇回顾(复习)性质的文章。涉及到的知识点有:二叉树,结构体,链表,链栈,递归,指针,DFS(搜索过程)。还算比较全面。


完整代码:

/*************************************************************************
	实现功能:	输出从根结点到指定结点的路径
	编译环境:	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
*************************************************************************/

参考

1、C语言程序设计教程(第二版). 王敬华 林萍 张清国 编著. 清华大学出版社.
2、数据结构(C语言版). 严蔚敏 吴伟明 编著. 清华大学出版社.


原文链接:https://blog.csdn.net/pfdvnah/article/details/102387839


- wowpH -
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值