在先序线索树中查找后继结点
在先序线索二叉树T中,查找给定结点在先序序列中的后继。
(1)编写二叉链表方式存储的二叉树建立函数;
(2)编写在二叉树上加先序线索函数;
(3)编写求后继结点函数;参考下面代码段
BiTNode PreNext(BiTNode p)
{ BiTNode next=NULL;
if(p->Ltag==0) next=p->Lchild;
else next=p->Rchild;
return next;
}
4)要求程序通过一个主菜单进行控制,通过选择菜单项序号调用各功能函数。
代码如下:
#include <stdio.h>
#include <malloc.h>
#define scanf_s scanf
// 定义二叉线索树节点
typedef struct BiThrNode
{
char data;
struct BiThrNode *lchild, *rchild; // 左右孩子指针
int LTag, RTag; // 左右标志
} BiThrNode, *BiThrTree;
BiThrTree pre;
BiThrTree next;
// 菜单
int SelectMenu();
// 创建二叉链表
void CreateBiTree(BiThrTree *bt);
// 叉树加上先序线索
void PreThreading(BiThrTree p);
// 查找值为key的结点函数
BiThrNode *Find(BiThrNode *T, char key);
// 查找指定结点的后继
BiThrNode * PreNext(BiThrNode *p);
// 先序遍历 线索二叉树
void PreOrder(BiThrNode* Root);
// 菜单驱动程序
int SelectMenu() {
int sn;
printf("-----------MENU---------\n"); // 显示菜单
printf("=========================================\n");
printf("1.----二叉树的建立------\n");
printf("2.----二叉树加上先序线索--------\n");
printf("3.----先序遍历线索二叉树--------\n");
printf("4.----查找给定结点*p在先序序列中的后继----\n");
printf("0.----退出程序----------\n");
printf("=========================================\n");
printf("请选择0--4:");
// 菜单功能选择
for (;;) {
scanf_s("%d", &sn); // 输入选项
getchar();
if (sn < 0 || sn > 4)
printf("\n 输入选择错误,请重新选择 0--4:");
else
break;
}
return sn;
}
/*TODO:二叉树的建立
功能描述:从键盘输入扩展的先序结点数据序列,'#'表示空结点,用二叉链表作为存储结构,建立二叉树。
例如:输入数据ab##c##,建立的二叉树如下:
a
b c
参数说明:bt-BiThrTree型指针参数
返回值说明:无
*/
void CreateBiTree(BiThrTree *bt)
{
char x;
x=getchar();
if(x=='#') *bt=NULL;
else
{
*bt=(BiThrTree)malloc(sizeof(BiThrNode));
(*bt)->data=x;
(*bt)->LTag=0;
(*bt)->RTag=0;
CreateBiTree(&((*bt)->lchild));
CreateBiTree(&((*bt)->rchild));
}
}
/*TODO:先序线索化
功能描述:编写在二叉树上加先序线索函数,给二叉树加上线索信息。
分别对左子树线索化,右子树线索化。
参数说明:p-BiThrTree型参数
返回值说明:无
*/
void PreThreading(BiThrTree p)
{
if(!p) return;
if(!p->lchild){
p->lchild=pre;
p->LTag=1;
}
else p->LTag=0;
if(pre&&!pre->rchild){
pre->rchild=p;
pre->RTag=1;
}
else p->RTag=0;
pre=p;
if(!p->LTag) PreThreading(p->lchild);
if(!p->RTag) PreThreading(p->rchild);
}
// 查找值为key的结点函数
BiThrNode *Find(BiThrNode *T, char key) {
BiThrNode *p, *q;
if (T != NULL) {
if (T->data == key) // 找到时,直接返回
return T;
else if (T->LTag != 1) { // 左孩子不为空,进入递归
p = Find(T->lchild, key);
if (p != NULL)
return p;
}
//右孩子不为空,进入递归
if (T->RTag != 1) {
q = Find(T->rchild, key);
if (q != NULL)
return q;
}
return NULL;
} else
return NULL;
}
/*TODO:查找指定结点的后继
功能描述:编写求后继结点函数,求出输入结点的后继结点信息。
参数说明:p-BiThrNode型指针
返回值说明:返回后继结点信息
*/
BiThrNode * PreNext(BiThrNode *p)
{
BiThrNode *q;
if(p->LTag==0) q=p->lchild;
else q=p->rchild;
return q;
}
// 先序遍历 线索二叉树
void PreOrder(BiThrNode* Root) {
if (Root == NULL) {
return;
}
BiThrNode* pCur = Root;
while (pCur != NULL) {
// 找到最左边的节点,左标记一直为0
while (pCur->lchild != NULL && pCur->LTag == 0) {
printf("%c ", pCur->data);
pCur = pCur->lchild;
}
// 左边的节点还没有访问
printf("%c ", pCur->data);
// 遇到线索 就看右节点
if (pCur->LTag == 1) {
pCur = pCur->rchild;
}
// 循环右节点
while (pCur != NULL) {
// 遇到左节点存在,则访问
if (pCur->lchild != NULL && pCur->LTag == 0) {
break;
}
printf("%c ", pCur->data);
pCur = pCur->rchild;
}
}
}
int main()
{
BiThrTree T;
char node;
BiThrTree q = NULL;
BiThrTree snode = NULL;
// 无限循环,选择0 退出
for (;;) {
// 调用菜单函数,按返回值选择功能函数
switch (SelectMenu()) {
case 1:
printf("输入数据,以#表示空结点:\n");
CreateBiTree(&T);
printf("\n");
break;
case 2:
printf("2.----在二叉树上加先序线索--------\n");
PreThreading(T); // 先序线索化
printf("\n");
break;
case 3:
printf("3.----先序遍历 线索二叉树--------\n");
PreOrder(T);
printf("\n");
break;
case 4:
printf("输入要查找后继的结点:\n");
scanf("%c", &node);
getchar();
snode = Find(T, node);
if (snode != NULL) {
printf("找到值为%c的结点\n", snode->data);
q = PreNext(snode);
if (q != NULL) {
printf("结点%c的后继结点是%c\n", snode->data, q->data);
} else {
printf("后继结点不存在\n");
}
} else {
printf("不存在值为%c的结点\n", node);
}
break;
case 0:
printf("\n0.----退出程序------------\n");
return 0;
} // switch语句结束
} // for循环结束
} // main()函数结束