我在这里不仅写了线索二叉树的普通代码,在代码中我还加入了线索化过程的打印,更好的帮助理解!
线索二叉树的概念
传统的二叉树存在很多空指针,能否利用这些空指针来存放指向其前驱或后继的指针?这样就可以像遍历单链表那样方便地遍历二叉树。引入线索二叉树正是为了加快查找结点前驱和后继的速度。 若无左子树,令lchild指向其前驱结点;若无右子树,令rchild指向其后继结点。如图所示,还需增加两个标志域标识指针域是指向左(右)孩子还是指向前驱(后继)。 这就是线索二叉树
中序线索二叉树的构造
二叉树的线索化是将二叉链表中的空指针改为指向前驱或后继的线索。而前驱或后继的信息只有在遍历时才能得到,因此线索化的实质就是遍历一次二叉树。 以中序线索二叉树的建立为例。附设指针 pre 指向刚刚访问过的结点,指针p 指向正在访问的结点,即pre指向p 的前驱。在中序遍历的过程中,检查p的左指针是否为空,若为空就将它指向pre;检查pre的右指针是否为空,若为空就将它指向p,如图所示。
中序线索二叉树的遍历
中序线索二叉树的结点中隐含了线索二叉树的前驱和后继信息。在对其进行遍历时,只要先找到序列中的第一个结点,然后依次找结点的后继,直至其后继为空。在中序线索二叉树中找结点后继的规律是:若其右标志为“1”,则右链为线索,指示其后继,否则遍历右子树中第一个访问的结点(右子树中最左下的结点)为其后继。
过程详解版代码
程序运行部分结果: 代码:
#include<iostream>
#include<cstdio>
#include<stdlib.h>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define TElemType char
#define Status int
typedef enum {Link, Thread} PointerTag;
typedef struct BiThrNode{
TElemType data;
struct BiThrNode *lchild, *rchild;
PointerTag LTag, RTag;
}BiThrNode, *BiThrTree;
int cnt = 0;
Status CreatBiThrTree(BiThrTree &T){
char ch;
cin >> ch;
if(ch == '#') T = NULL;
else{
if(!(T = (BiThrNode*)malloc(sizeof(BiThrTree)))) exit(OVERFLOW);
T->data = ch;
T->LTag = Link;
T->RTag = Link;
CreatBiThrTree(T->lchild);
CreatBiThrTree(T->rchild);
}
return OK;
}
void Visualize(BiThrTree p, BiThrTree pre){
cout << "p指向的结点:";
if(p != NULL) cout << p->data << '\t';
else cout << "NULL\t";
cout << "pre指向的结点:";
if(pre != NULL) cout << pre->data << endl;
else cout << "NULL" << endl;
}
Status InThread(BiThrTree &p, BiThrTree &pre){
Visualize(p, pre);
if(p != NULL){
cout << "------------------------------------>线索化" << p->data << "的左子树" << endl;
InThread(p->lchild, pre);
cout << "------------------------------------>" << p->data << "的左子树线索化完成" << '\t';
if(p->lchild == NULL){
cout << p->data << "的前驱节点指向pre指向的结点" << endl;
p->lchild = pre;
p->LTag = Thread;
}
if(pre != NULL && pre->rchild == NULL){
cout << pre->data << "的后继结点指向" << p->data << endl;
pre->rchild = p;
pre->RTag = Thread;
}
cout << "pre指向p所指向的结点" << endl;
pre = p;
cout << "------------------------------------>线索化" << p->data << "的右子树" << endl;
InThread(p->rchild, pre);
cout << "------------------------------------>" << p->data << "的右子树线索化完成" << endl;
cout << ++cnt << "次线索化之后:";
Visualize(p, pre);
cout << endl << endl;
}
return OK;
}
Status CreatInThread(BiThrTree &T){
BiThrTree pre = NULL;
if(T != NULL){
InThread(T, pre);
pre->rchild = NULL;
pre->RTag = Thread;
}
return OK;
}
void visit(BiThrNode *p){
cout << p->data;
}
void InOrder(BiThrTree T){
if(T != NULL){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
BiThrNode *FirstNode(BiThrNode *p){
while(p->LTag != Thread) p = p->lchild;
return p;
}
BiThrNode *NextNode(BiThrNode *p){
if(p->RTag == Link)
return FirstNode(p->rchild);
else return p->rchild;
}
void InThreadOrder(BiThrTree T){
for(BiThrNode *p = FirstNode(T); p != NULL; p = NextNode(p))
visit(p);
}
int main(){
cout << "---------------这是一个线索二叉树程序!---------------" << endl;
cout << "-------------首先按照先序序列建立一棵线索二叉树-------" << endl << endl;
cout << "按照先序序列输入二叉树中结点的值(一个字符),#表示空树" << endl;
BiThrTree T;
CreatBiThrTree(T);
cout << "二叉树的递归中序遍历:";
InOrder(T);
cout << endl << endl << "-------------下面进行中序线索化-------------" << endl;
cout << "--------------打印线索化的过程--------------" << endl;
if(CreatInThread(T) == 1) cout << "--------------已完成线索化--------------" << endl;
cout << "中序线索二叉树的非递归遍历序列:";
InThreadOrder(T);
return 0;
}
纯享版代码
#include<iostream>
#include<cstdio>
#include<stdlib.h>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define TElemType char
#define Status int
typedef enum {Link, Thread} PointerTag;
typedef struct BiThrNode{
TElemType data;
struct BiThrNode *lchild, *rchild;
PointerTag LTag, RTag;
}BiThrNode, *BiThrTree;
Status CreatBiThrTree(BiThrTree &T){
char ch;
cin >> ch;
if(ch == '#') T = NULL;
else{
if(!(T = (BiThrNode*)malloc(sizeof(BiThrTree)))) exit(OVERFLOW);
T->data = ch;
T->LTag = Link;
T->RTag = Link;
CreatBiThrTree(T->lchild);
CreatBiThrTree(T->rchild);
}
return OK;
}
Status InThread(BiThrTree &p, BiThrTree &pre){
if(p != NULL){
InThread(p->lchild, pre);
if(p->lchild == NULL){
p->lchild = pre;
p->LTag = Thread;
}
if(pre != NULL && pre->rchild == NULL){
pre->rchild = p;
pre->RTag = Thread;
}
pre = p;
InThread(p->rchild, pre);
}
return OK;
}
Status CreatInThread(BiThrTree &T){
BiThrTree pre = NULL;
if(T != NULL){
InThread(T, pre);
pre->rchild = NULL;
pre->RTag = Thread;
}
return OK;
}
void visit(BiThrNode *p){
cout << p->data;
}
void InOrder(BiThrTree T){
if(T != NULL){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
BiThrNode *FirstNode(BiThrNode *p){
while(p->LTag != Thread) p = p->lchild;
return p;
}
BiThrNode *NextNode(BiThrNode *p){
if(p->RTag == Link)
return FirstNode(p->rchild);
else return p->rchild;
}
void InThreadOrder(BiThrTree T){
for(BiThrNode *p = FirstNode(T); p != NULL; p = NextNode(p))
visit(p);
}
int main(){
BiThrTree T;
CreatBiThrTree(T);
CreatInThread(T);
cout << "遍历序列:";
InThreadOrder(T);
return 0;
}
|