数据结构(c)-线索二叉树

线索二叉树

实训08-线索二叉树的创建及遍历(驾照审验)
题目:根据提供的驾照审验流程,建立相应的二叉树并进行前序线索化遍历算法。

要求:用二叉树的线索链表存储方法,实现前序遍历算法,并查找"交管所审验"的直接前驱

附图:驾照审验.png

/*
前序遍历:
驾照审验 网上审验 审验申请 审验教育 审验学习 学时审验 审验通过 审验失败
交管所审验 审验申请 现场学习 审验通过 审验失败
*/

[]: https://cloud.tencent.com/developer/article/1820106 "线索二叉树的原理及创建"

上面这个博客讲的非常好

推荐 有啥不明白的看上面那个博客

图解 永远的神

2021.11.10更新 题目看错了.....代码已更新

完整代码
#include <stdio.h>
#include <malloc.h>

typedef enum{
	false = 0,
	true = 1
}bool;
typedef enum {
	pre=0,
	next=1
}relation;

typedef struct Node {
	struct Node* lChild;
	int lFlag;//为0表示有左孩子    为1表示线索(没有左孩子)   lChild指向直接前驱   
	char* regionName;
	struct Node* rChild;
	int rFlag;//为0表示有右孩子    为1表示线索(没有右孩子)   rChild指向直接后继   
}node;


node* InitBinaryTree(char* regionNames[],int startIndex,int len) {
	if (startIndex >= len || regionNames[startIndex]=="#") {
		return NULL;
	}
	node* root = malloc(sizeof(node));
	if (root != NULL) {
		root->regionName = regionNames[startIndex];
		root->lFlag = 0;
		root->rFlag = 0;
		root->lChild = InitBinaryTree(regionNames, startIndex * 2 + 1, len);
		root->rChild = InitBinaryTree(regionNames, startIndex * 2 + 2, len);
	}
	return root;
}


node* pp;//这个指针一定要移出来 作为一个全局指针,不然递归时会作为存在栈中 右线索指向会有问题
void PreorderTraversal(node* root) {
	if (root == NULL)
		return;
	if (root->lChild == NULL) {//没有左孩子时  也就是在前序遍历中当前节点没有直接前继元素
		root->lFlag = 1;//设为线索标志
		root->lChild = pp;//将上一次遍历的节点设为 当前节点的直接前继
	}
	if (pp != NULL && pp->rChild == NULL) {
		pp->rFlag = 1;
		pp->rChild = root;
	}
	printf("%s\t", root->regionName);
	pp = root;
	if (root->lFlag == 0) {
		PreorderTraversal(root->lChild);
	}
	if (root->rFlag == 0) {
		PreorderTraversal(root->rChild);
	}
}

void MidorderTraversal(node* root) {
	if (root == NULL)
		return;
	
	MidorderTraversal(root->lChild);
	if (root->lChild == NULL) {
		root->lFlag = 1;
		root->lChild = pp;
	}
	if (pp != NULL && root->rChild == NULL) {
		pp->rFlag = 1;
		pp->rChild = root;
	}
	printf("%s\t", root->regionName);
	pp = root;
	MidorderTraversal(root->rChild);
}

void PostorderTraversal(node* root) {
	if (root == NULL)
		return;

	PostorderTraversal(root->lChild, pp);
	
	PostorderTraversal(root->rChild, pp);
	if (root->lChild == NULL) {
		root->lFlag = 1;
		root->lChild = pp;
	}
	if (pp != NULL && root->rChild == NULL) {
		pp->rFlag = 1;
		pp->rChild = root;
	}
	printf("%s\t", root->regionName);
	pp = root;
}

void PrintNodeRelation(node* root,char* name,relation rela) {
	node* p = root;
	bool hasNode = false;
	node* preNode=root;
	while (p && !hasNode) {
		while (p->lFlag==0)
		{
			//printf("%s\t", p->regionName);
			if (p->regionName == name) {
				hasNode = true;
				break;
			}
			p = p->lChild;
		}
		
		//printf("%s\t", p->regionName);
		if (p->regionName == name) {
			hasNode = true;
			break;
		}
		preNode = p;//此时走这里表示当前结点的下一个结点是一个线索结点  存下来   
							//下一个结点如果正好是所要匹配的结点时  那个结点的前驱就是preNode
		p = p->rChild;
	}
	if (hasNode) {
		if (rela == pre) {
			printf("【%s】的直接前驱是:【%s】\n", p->regionName, preNode->regionName);
		}
	}
	
}

int main() {
	char* regionNames[] = { "驾照审验",
									"网上审验","交管所审验",
		"审验申请","审验教育",					"审验申请","现场学习",
		"#","#","审验学习","学时审验",   "#","#",   "审验通过","审验失败",
"#","#","#","#",	"#","#",	"审验通过","审验失败"};

	/*char* regionNames[] = { "a",
							"b",					"c",
						"d",	"e",			"f",	"g",
					"#","#","h","i", "#","#","j","k" };*/
	int len = sizeof(regionNames) / sizeof(regionNames[0]);
	node* root = InitBinaryTree(regionNames, 0, len);
	PreorderTraversal(root,NULL);
	printf("\n\n");
	PrintNodeRelation(root, "交管所审验", pre);
	/*printf("\n\n");
	root = InitBinaryTree(regionNames, 0, len);
	MidorderTraversal(root, NULL);
	printf("\n\n");
	root = InitBinaryTree(regionNames, 0, len);
	PostorderTraversal(root, NULL);*/
	system("Pause");
}

运行结果

posted @ 2021-11-06 15:26  无涯ha  阅读(74)  评论(0编辑  收藏  举报