二叉樹根結點到任意結點的路徑(C語言)

有一棵二叉樹,以下圖所示:node

二叉樹

其中 # 表示空結點。web

先序遍歷:A B D E G C Fsvg

問題:怎麼獲得從根結點到任意結點的路徑呢?函數

示例:輸入 G,怎麼獲得從結點 A 到結點 G 的路徑呢?優化

很明顯,咱們一眼就能看出來路徑是 A B E G。如何經過程序獲得這條路徑就是咱們接下來須要作的。spa

定義二叉樹的 鏈式存儲結構 以下:.net

typedef struct BiTNode {
	char data;
	struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;// 二叉樹結點的存儲結構

二叉樹的遍歷有三種方式:即先序遍歷,中序遍歷,後序遍歷。code

先序遍歷是先訪問結點再遞歸子樹。咱們只須要訪問到目標結點的時候就知道了路徑就能夠結束遞歸,所以正好符合要求。另外兩個也能夠獲得路徑,可是還要先訪問子樹,顯然是不必的。xml

先序遍歷能夠經過遞歸實現,咱們只須要加個容器來保存路徑便可。 正好知足要求。因爲不知道路徑的長度,所以採用 鏈棧 來實現。blog

鏈棧 結構以下:

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("一、先序輸入二叉樹\n");
	printf("二、空結點用'%c'表示\n", EMPTY_NODE);
	printf("三、Enter表示輸入結束\n");
	printf("四、字符個數必須正確\n");
}

/************************************************************************* 一、先序輸入二叉樹 二、空結點用'#'表示 三、Enter表示輸入結束 四、字符個數必須正確 示例1: 輸入二叉樹:ABD##EG###CF### 輸入指定結點:G 路徑:A B E G 示例2: 輸入二叉樹:124##56##7##3## 輸入指定結點:7 路徑:1 2 5 7 *************************************************************************/
相關文章
相關標籤/搜索