您的位置:首页 > 其它

二叉线索树

2015-09-16 14:40 330 查看
线索化是为了能够像链表一样遍历树。

线索化概念

1、前言

普通二叉树只能找到结点的左右孩子信息,而该结点的直接前驱和直接后继只能在遍历过程中获得。

若可将遍历后对应的有关前驱和后继预存起来,则从第一个结点开始就能很快“顺藤摸瓜”而遍历整个树了。

二叉线索树思想是干什么的?



中序遍历这棵树===》转换成链表访问

2线索化思想







结论:线索化过程就是在遍历过程(假设是中序遍历)中修改空指针的过程:

将空的lchild改为结点的直接前驱;

将空的rchild改为结点的直接后继。

3线索化思想训练



请将此树线索化。

1)右空指针线索化:



2)左空指针线索化



3)总结



线索化的实现

1)线索化树结点

typedef struct BiThrNode /* 二叉线索存储结点结构 */

{

char data; /* 结点数据 */

struct BiThrNode *lchild, *rchild; /* 左右孩子指针 */

int LTag;

int RTag; /* 左右标志 */

} BiThrNode, *BiThrTree;

2)线索化思想分析



线索化的本质:让前后结点,建立关系;

1)两个辅助指针变量形成差值后:后继结点的左孩子指向前驱结点,前驱结点的右孩子指向后继结点。

2)赋值指针变量和业务操作的逻辑关系





二叉树线索化树的遍历

/* 中序遍历二叉线索树T(头结点)的非递归算法 */
int InOrderTraverse_Thr(BiThrNode* T)
{
BiThrNode* p;
p = T->lchild; /* p指向根结点 */
while (p != T)
{
/* 空树或遍历结束时,p==T */
while (p->LTag == Link)
p = p->lchild;
printf("%c ", p->data);

while (p->RTag==Thread && p->rchild!=T)
{
p = p->rchild;
printf("%c ", p->data);
}
p=p->rchild;
}
return 0;
}


创建树:

#define  _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

typedef struct BiTNode
{
int        data;
struct BiTNode *lchild, *rchild;
}BiTNode;

typedef struct BiTNode * BiTree;

void InOrder(BiTNode *T)
{
if (T == NULL)
{
return ;
}

if (T->lchild != NULL)
{
InOrder(T->lchild);
}

printf("%c ", T->data); //

if (T->rchild != NULL)
{
InOrder(T->rchild);
}
}

// "1##"
// 124###3##

//创建树 用先序
BiTNode *BiTree_Creat()
{
BiTNode  *tmp = NULL;
char  ch;
scanf("%c", &ch);

if (ch == '#')
{
return NULL;
}
else
{

tmp = (BiTNode *) malloc(sizeof(BiTNode)); //创建结点
if (tmp == NULL)
{
return NULL;
}
tmp->data = ch;
tmp->lchild = NULL;
tmp->rchild = NULL;
//在创建结点的左子树
tmp->lchild = BiTree_Creat();
tmp->rchild = BiTree_Creat();
return tmp;
}
}

//释放树 选释放左子树 在释放右子树 在释放根结点
void BiTree_Free(BiTNode *T)
{
if (T == NULL)
{
return ;
}

if (T->lchild != NULL)
{
BiTree_Free(T->lchild); //释放左子树 把左子树的根结点 传给释放函数
T->lchild = NULL;
}

if (T->rchild != NULL)
{
BiTree_Free(T->rchild);
T->rchild = NULL;
}

free(T);

//

}
void main()
{
BiTNode  *T = NULL;
printf("#号法创建树 请输入字符串 ( 124###3## ): ");
T  = BiTree_Creat();
InOrder(T);

BiTree_Free(T);

printf("hello...\n");
system("pause");
return ;
}


树的线索化:

#define  _CRT_SECURE_NO_WARNINGS
#include "string.h"
#include "stdio.h"
#include "stdlib.h"

/* Link==0表示指向左右孩子指针, */
/* Thread==1表示指向前驱或后继的线索 */
#define Thread 1
#define Link    0

typedef  struct BiThrNode    /* 二叉线索存储结点结构 */
{
char        data;    /* 结点数据 */
struct BiThrNode *lchild, *rchild;    /* 左右孩子指针 */
int            LTag;
int            RTag;        /* 左右标志 */
} BiThrNode, *BiThrTree;

char Nil='#'; /* 字符型以空格符为空 */

/* 按前序输入二叉线索树中结点的值,构造二叉线索树T */
BiThrNode* CreateBiThrTree()
{
BiThrNode *tmp = NULL;
char ch;
scanf("%c",&ch);

if (ch == '#')
{
return NULL;
}
else
{
tmp = (BiThrNode *)malloc(sizeof(BiThrNode));
if (tmp == NULL)
{
return NULL;
}
memset(tmp, 0, sizeof(BiThrNode));
tmp->data = ch;

tmp->lchild = CreateBiThrTree(); /* 递归构造左子树 */
tmp->rchild = CreateBiThrTree();
}
return tmp;
}

BiThrNode  *pre; /* 全局变量,始终指向刚刚访问过的结点 */
/* 中序遍历进行中序线索化 */
void InThreading(BiThrNode *p)
{
if(p)
{
InThreading(p->lchild); // 递归左子树线索化
if(p->lchild == NULL)    // 没有左孩子
{
p->LTag = Thread;      p->lchild = pre;    //前驱线索 左孩子指针指向前驱
}
if(pre->rchild == NULL) // 前驱没有右孩子
{
pre->RTag = Thread;  pre->rchild = p;    // 后继线索 前驱右孩子指针指向后继(当前结点p)
}
pre = p;                // 保持pre指向p的前驱
InThreading(p->rchild); // 递归右子树线索化
}
}

/* 中序遍历二叉树T,并将其中序线索化,Thrt指向头结点 */
BiThrNode* InOrderThreading(BiThrTree T)
{
BiThrNode *Thrt = NULL;

Thrt = (BiThrNode *)malloc(sizeof(BiThrNode)); //建头结点
if (Thrt == NULL)
{
return NULL;
}
memset(Thrt, 0, sizeof(BiThrNode));

Thrt->LTag = Link;  //左孩子为孩子指针
Thrt->RTag = Thread; //右孩子为线索化的指针
Thrt->rchild = Thrt; // 右指针回指 */  //步骤2和4
if(T == NULL) // 若二叉树空,则左指针回指
{
Thrt->lchild  = Thrt; //步骤1和3
}
else
{
Thrt->lchild = T;    //步骤1
pre = Thrt ;
InThreading(T);        // 中序遍历进行中序线索化
pre->rchild = Thrt;    //步骤4
pre->RTag = Thread;    // 最后一个结点线索化
Thrt->rchild = pre;    //步骤2
}
return Thrt;
}

/* 中序遍历二叉线索树T(头结点)的非递归算法 */
int InOrderTraverse_Thr(BiThrNode* T)
{
BiThrNode* p;
p = T->lchild; /* p指向根结点 */
while (p != T)
{
/* 空树或遍历结束时,p==T */
while (p->LTag == Link)
p = p->lchild;
printf("%c ", p->data);

//如果中序遍历的最后一个结点的 右孩子 == T 说明到最后一个结点 ,遍历结束..
while (p->RTag==Thread && p->rchild!=T)
{
p = p->rchild;
printf("%c ", p->data);
}
p = p->rchild;
}
return 0;
}

/* 中序遍历二叉线索树T(头结点)的非递归算法 */
int InOrderTraverse_Thr2(BiThrNode* T)
{
BiThrNode* p;
p = T->rchild; /* p指向根结点 */
while (p != T)
{
/* 空树或遍历结束时,p==T */
while (p->RTag == Link)
p = p->rchild;
printf("%c ", p->data);

//如果中序遍历的最后一个结点的 右孩子 == T 说明到最后一个结点 ,遍历结束..
while (p->LTag==Thread && p->lchild!=T)
{
p = p->lchild;
printf("%c ", p->data);
}
p = p->lchild;
}
return 0;
}

int main()
{
BiThrTree T, H;
printf("请按前序输入二叉树(如:'ABDH##I##EJ###CF##G##')\n");
T = CreateBiThrTree(); // 按前序产生二叉树
H = InOrderThreading(T); // 中序遍历,并中序线索化二叉树
printf("中序遍历(输出)二叉线索树:\n");
InOrderTraverse_Thr(H); // 中序遍历(输出)二叉线索树

printf("\n逆序访问:");
InOrderTraverse_Thr2(H);

printf("\n");

system("pause");
return 0;
}


04 09完
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: