数据结构(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");
}
运行结果