Any binary tree root node to the path (C language)

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/pfdvnah/article/details/102387839

There are a binary tree, as shown below:

Binary Tree

Wherein #represents null node.

Preorder: ABDEGCF

Question: how to get the path from the root to any node of it?

Example: Enter G, how to get from node Ato node Gpath of it?

Obviously, we tell at a glance the path is ABEG. How to get this path through the program is what we need to do next.

Definition of binary tree Storage Structure as follows:

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

Traversing the binary tree, there are three ways: i.e. preorder, preorder, postorder traversal.

Preorder traversal to access node is recursively sub-tree. We just need access to the target node to know when the end of the path can be recursive, thus fit the bill. The other two paths can also be obtained, but also to visit sub-tree, it is clearly not necessary.

Preorder can be implemented recursively, we only need to add a container to hold the path. Stack just to meet the requirements. Because the path length is not known, so a link stack is achieved.

Link stack structure is as follows:

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

Complete code:

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

Guess you like

Origin blog.csdn.net/pfdvnah/article/details/102387839