/**
* 线索二叉树概念:
* 对于n个结点的二叉树,在二叉树链式存储结构中有n+1个空链域,
* 利用这些空链域存放在某种遍历次序下该结点的前驱结点和后继
* 结点的指针,这些指针称为线索,加上线索的二叉树称为线索二
* 叉树。
* 实验题目:
* 实现中序线索化二叉树
* 实验目的:
* 领会线索二叉树的构造过程以及构造线索二叉树的算法设计
* 实验内容:
* 设计程序,实现二叉树的中序线索化,采用递归和非递归两
* 种方法输出中序线索二叉树的中序序列。
*/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node
{
ElemType data; // 数据元素
int ltag; // 增加的线索标记
int rtag;
struct node *lchild; // 指向左孩子结点
struct node *rchild; // 指向右孩子结点
}TBTNode; // 声明二叉链结点类型
/*---------------由字符串str建立含空线索域的二叉链---------------*/
// char *str = "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))";
void CreateTBTNode(TBTNode *&b, char *str)
{
TBTNode *p = NULL;
TBTNode *St[MaxSize]; // 栈(指针数组)
int top = -1; // 栈指针
int k;
int j = 0;
char ch;
b = NULL; // 建立的二叉树初始时为空
ch = str[j];
// printf("start %s, ch = %c\n", __func__, ch);
while(ch != '\0') // 字符串未扫描完时循环
{
switch(ch)
{
case '(': // 为左结点
top++;
St[top] = p;
k = 1;
break;
case ')':
top--;
break;
case ',': // 为右结点
k = 2;
break;
default:
p = (TBTNode *)malloc(sizeof(TBTNode));
p->data = ch;
p->lchild = p->rchild = NULL;
if(b == NULL) // p为二叉树的根结点
b = p;
else // 已建立二叉树根结点
{
switch(k)
{
case 1: // 设置左结点
St[top]->lchild = p;
break;
case 2: // 设置右结点
St[top]->rchild = p;
break;
}
}
break;
}
j++;
ch = str[j];
// printf("%s, ch = %c\n", __func__, ch);
}
}
/*------------------------输出含空线索域的二叉树------------------------*/
void DispTBTNode(TBTNode *b)
{
if(b != NULL)
{
printf("%c", b->data);
if((b->lchild != NULL) || (b->rchild != NULL))
{
printf("(");
DispTBTNode(b->lchild);
if(b->rchild != NULL)
printf(",");
DispTBTNode(b->rchild);
printf(")");
}
}
}
TBTNode *pre; // 全局变量
static void Thread(TBTNode *&p) // 指针的引用
{
if(p != NULL){
Thread(p->lchild); // 左子树线索化
if(p->lchild == NULL){ // 前驱线索
p->lchild = pre;
p->ltag = 1;
}else{
p->ltag = 0;
}
if(pre->rchild == NULL){ // 后继线索
pre->rchild = p; // 建立前驱结点的后继线索
pre->rtag = 1;
}else{
pre->rtag = 0;
}
pre = p;
Thread(p->rchild); // 右子树线索化
}
}
/*-------------------中序线索化二叉树----------------------*/
// char *str = "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))";
TBTNode * CreateThread(TBTNode *b)
{
TBTNode *root;
root = (TBTNode *)malloc(sizeof(TBTNode)); // 创建根结点
root->ltag = 0; // 设置根结点左线索标记为0
root->rtag = 1; // 设置根结点右线索标记为1
root->rchild = b; // 设置根结点的右孩子结点为二叉树的根结点
if(b == NULL) // 空二叉树
root->lchild = root;
else // 二叉树非空
{
//printf("二叉树b非空\n");
root->lchild = b;
pre = root;
Thread(b); // 中序遍历线索化二叉树
pre->rchild = root;
pre->rtag = 1;
root->rchild = pre; // 根结点右线索化
}
return root;
}
/*-----------------------中序线索化二叉树中实现中序遍历------------------------*/
void ThInOrder(TBTNode *tb)
{
TBTNode *p = tb->lchild; // 指向根结点
while(p != tb){
while(p->ltag == 0)
p = p->lchild;
printf("%c ", p->data);
while(p->rtag == 1 && p->rchild != tb){
p = p->rchild;
printf("%c ", p->data);
}
p = p->rchild;
}
}
int main(void)
{
TBTNode *b;
TBTNode *tb;
char *str = NULL;
str = (char *)malloc(MaxSize);
memset(str, 0, MaxSize);
strcpy(str, "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
CreateTBTNode(b, str);
printf("二叉树:");
DispTBTNode(b);
printf("\n");
tb = CreateThread(b);
printf("线索中序序列:");
ThInOrder(tb);
printf("\n");
return 0;
}
测试结果:
二叉树:A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))
线索中序序列:D B J H L K M N E A F C G I