线索二叉树的建立很需要思维能力,尽量把原理弄懂在去查看代码。
二叉树线索化
二叉树的遍历是按照一定的规则把二叉树中的节点按照一定的次序排列成线性序列进行访问的,实质上就是对一个非线性结构进行线索化操作,使得每个节点(除第一个和最后一个外)都有前驱和后继节点,有时为了运算方便需要记录这些前驱和后继节点,称为二叉树线索化,而对于不同的遍历规则,又分为先序线索二叉树,中序线索二叉树(常用),后序线索二叉树。
思路:
一颗具有n个节点的二叉树,有n-1条指向左孩子或右孩子的分支,对于二叉链表来说,2n个指针只用了n-1个,所以可以利用另外n+1个指针作为指向前驱节点和后继节点的指针。
图一是InThreading函数所做的事情(通过中序遍历的方式把所有节点连接起来)
图二是addmiddleNode函数所做的事情,一般是增加头节点后再取调用InThreading函数。
#include <bits/stdc++.h>
using namespace std;
typedef char Elemtype;
typedef int Elemtvar;
/**
定义结构体
*/
typedef struct BitNode{
Elemtype data;
Elemtvar ltag,rtag; //0代表左/右孩子 1代表前驱/后驱
BitNode *lchilid,*rchild; //左节点,右节点
}BitNode,*BitTree;
/**
创建链表
*/
void createBitTree(BitTree &p){
char data;
scanf("%c",&data);
if(data=='#'){
p=NULL;
}else{
p=new BitNode; //分配指针存储空间
p->data=data;
p->ltag=0;
p->rtag=0;
createBitTree(p->lchilid);
createBitTree(p->rchild);
}
}
/**
打印链表
中序打印
*/
void printTree(BitTree &p){
if(p){
printTree(p->lchilid);
cout<<p->data;
printTree(p->rchild);
}
}
/**
线索化二叉树
类似中序遍历(作用是把普通的二叉树叶子节点上增加前驱与后驱,这样就变成了线索二叉树)
*/
BitTree pre=NULL;
void InThreading(BitTree &tree){
if(tree!=NULL){
InThreading(tree->lchilid);
if(tree->lchilid==NULL&&tree->ltag==0){
tree->ltag=1;
tree->lchilid=pre;
}
if(pre->rchild==NULL&&pre->rtag==0){
pre->rtag=1;
pre->rchild=tree;
}
pre=tree; //保持pre指向tree的前驱,pre指向刚刚访问过的结点
InThreading(tree->rchild);
}
}
/**
以中序遍历增加头节点(这个程序负责生成一个头节点)
*/
BitTree addmiddleNode(BitTree &p){
BitTree Thrt=new BitNode; //创建头节点
if(Thrt==NULL) return NULL;
memset(Thrt,0,sizeof(BitNode));
Thrt->ltag=0; //0为孩子指针
Thrt->rtag=1; //1为线索化指针
Thrt->rchild=Thrt; //右指针回指
if(p==NULL) { //左指针回指
Thrt->lchilid=NULL;
}else{
Thrt->lchilid=p;
pre=Thrt;
InThreading(p); //中序遍历进行中序线索化
Thrt->rchild=pre;
pre->rtag=1; //最后一个节点线索化
pre->rchild=Thrt;
}
return Thrt;
}
/**
中序遍历二叉树线索数T头节点的非递归算法
*/
void InorderTraverse(BitTree &T){
BitTree p;
p=T->lchilid;
while(p!=T){
//空树或者遍历结束
while(p->ltag==0)
p=p->lchilid;
cout<<p->data;
while(p->rtag==1&&p->rchild!=T){ //中间节点
p=p->rchild;
cout<<p->data;
}
p=p->rchild;
}
}
int main(){
BitTree tree;
createBitTree(tree); //创建二叉树
tree=addmiddleNode(tree); //以中序遍历增加头节点
//printTree(tree);
InorderTraverse(tree); //中序遍历
return 0;
}
附录:
https://blog.csdn.net/szu_crayon/article/details/81050911
我的二叉树线索化思路部分是直接copy的这位博主的文字,而且我看了一下他的图片也很清晰(我不会画图.......)。如果觉得本人写的不好可以去这位博主的主页观看。