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


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

二叉樹

其中 # 表示空結點。

先序遍歷: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 *************************************************************************/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM