学数据结构的时候没有学线索二叉树,现在考研需要,补上了。
线索二叉树中给每个节点加上标记,使叶节点的空的数据域填上前驱或者后继,使得线索二叉树能快速的找到前驱后继。
中序线索二叉树
线索化时如节点左子树为空,则添加前驱;设置全局变量pre,保存上一个访问的节点,访问下一个节点时,如果pre右子树为空,则pre的后继连上此节点。
#include<stdio.h>
#include<stdlib.h>
#define N 100
typedef int ElemType;
typedef struct ThreadNode{
ElemType data;
struct ThreadNode *lchild,*rchild;
int ltag,rtag; //左右线索
}ThreadNode,*ThreadTree;
ThreadNode *pre=NULL;
void visit(ThreadNode *q){
if(q->lchild==NULL){
q->lchild=pre;
q->ltag=1;
}
if(pre&&pre->rchild==NULL){
pre->rchild=q;
pre->rtag=1;
}
pre=q;
}
void InThread(ThreadTree T){ //边遍历边线索化
if(T){
InThread(T->lchild);
visit(T); //后序调一下位置即可
InThread(T->rchild);
}
}
void CreatInThread(ThreadTree T){ //线索化二叉树
pre=NULL;
if(T){
InThread(T);
if(pre->rchild==NULL){ //如果最后一点为空,给他加标记
pre->rtag=1;
}
}
}
ThreadNode *Firstnode(ThreadNode *p){ //p的第一个被中序遍历的节点
while(p->ltag==0) p=p->lchild;
return p;
}
ThreadNode *Nextnode(ThreadNode *p){ //中序线索二叉树中p的后继
if(p->rtag==0) return Firstnode(p->rchild);
else return p->rchild;
}
void Inoder(ThreadNode *T){ //非递归中序遍历二叉树
ThreadNode *p;
for(p=Firstnode(T);p!=NULL;p=Nextnode(p)){
printf("%d ",p->data);
}
printf("\n");
}
ThreadNode *Lastnode(ThreadNode *p){ //p的最后一个被中序遍历的节点
while(p->rtag==0) p=p->rchild;
return p;
}
ThreadNode *Prenode(ThreadNode *p){ //中序线索二叉树中p的前继
if(p->ltag==0) return Lastnode(p->lchild);
else return p->lchild;
}
void RevInoder(ThreadNode *T){ //非递归逆向中序遍历二叉树
ThreadNode *p;
for(p=Lastnode(T);p!=NULL;p=Prenode(p)){
printf("%d ",p->data);
}
printf("\n");
}
ThreadTree Creat(ThreadTree T,int x){
if(!T){
ThreadTree T=(ThreadTree)malloc(sizeof(ThreadNode));
T->data=x;
T->lchild=T->rchild=NULL;
T->ltag=T->rtag=0;
}
else {
if(x>T->data){
T->rchild=Creat(T->rchild,x);
}
else{
T->lchild=Creat(T->lchild,x);
}
}
}
int main()
{
int i,j,k;
int a[10]={2,5,6,9,3,4,7,8,1,0};
ThreadTree T;
for(i=0;i<9;i++){
T=Creat(T,a[i]);
}
CreatInThread(T);
Inoder(T);
RevInoder(T);
return 0;
}
先序线索二叉树
先序线索二叉树实现同中序基本一致,要注意的点是左边节点的数据可能是线索并不是真正的左子树,所以在遍历的时候加上一个判断条件。
#include<stdio.h>
#include<stdlib.h>
#define N 100
typedef int ElemType;
typedef struct ThreadNode{
ElemType data;
struct ThreadNode *lchild,*rchild;
int ltag,rtag; //左右线索
}ThreadNode,*ThreadTree;
ThreadNode *pre=NULL;
void visit(ThreadNode *q){
if(q->lchild==NULL){
q->lchild=pre;
q->ltag=1;
}
if(pre&&pre->rchild==NULL){
pre->rchild=q;
pre->rtag=1;
}
pre=q;
}
void PreThread(ThreadTree T){ //边遍历边线索化
if(T){
visit(T);
if(T->ltag==0){ //防止左边为线索无限循环的问题
PreThread(T->lchild);
}
PreThread(T->rchild);
}
}
void CreatPreThread(ThreadTree T){ //线索化二叉树
pre=NULL;
if(T){
PreThread(T);
if(pre->rchild==NULL){ //如果最后一点为空,给他加标记
pre->rtag=1;
}
}
}
ThreadTree Creat(ThreadTree T,int x){
if(!T){
ThreadTree T=(ThreadTree)malloc(sizeof(ThreadNode));
T->data=x;
T->lchild=T->rchild=NULL;
}
else {
if(x>T->data){
T->rchild=Creat(T->rchild,x);
}
else{
T->lchild=Creat(T->lchild,x);
}
}
}
ThreadNode *NextNode(ThreadNode *p){ //先序二叉树的后继
if(p->rtag==1) return p->rchild;
else {
if(p->lchild) return p->lchild;
else return p->rchild;
}
}
int main()
{
int i,j,k;
int a[10]={2,5,6,9,3,4,7,8,1,0};
ThreadTree T=(ThreadTree)malloc(sizeof(ThreadNode));
T->data=a[0];
T->lchild=T->rchild=NULL;
for(i=1;i<9;i++){
T=Creat(T,a[i]);
}
CreatPreThread(T);
printf("%d",NextNode(T)->data);
return 0;
}
后序线索二叉树
后序线索二叉树同中序线索二叉树实现基本一致,遍历的时候调一下顺序就可。
#include<stdio.h>
#include<stdlib.h>
#define N 100
typedef int ElemType;
typedef struct ThreadNode{
ElemType data;
struct ThreadNode *lchild,*rchild;
int ltag,rtag; //左右线索
}ThreadNode,*ThreadTree;
ThreadNode *pre=NULL;
void visit(ThreadNode *q){
if(q->lchild==NULL){
q->lchild=pre;
q->ltag=1;
}
if(pre&&pre->rchild==NULL){
pre->rchild=q;
pre->rtag=1;
}
pre=q;
}
void PostThread(ThreadTree T){ //边遍历边线索化
if(T){
visit(T);
if(T->ltag==0){ //防止左边为线索无限循环的问题
PostThread(T->lchild);
}
PostThread(T->rchild);
}
}
void CreatPostThread(ThreadTree T){ //线索化二叉树
pre=NULL;
if(T){
PostThread(T);
if(pre->rchild==NULL){ //如果最后一点为空,给他加标记
pre->rtag=1;
}
}
}
ThreadTree Creat(ThreadTree T,int x){
if(!T){
ThreadTree T=(ThreadTree)malloc(sizeof(ThreadNode));
T->data=x;
T->lchild=T->rchild=NULL;
}
else {
if(x>T->data){
T->rchild=Creat(T->rchild,x);
}
else{
T->lchild=Creat(T->lchild,x);
}
}
}
ThreadNode *PreNode(ThreadNode *p){
if(p->ltag==1) return p->lchild;
else {
if(p->rchild) return p->rchild;
else return p->lchild;
}
}
int main()
{
int i,j,k;
int a[10]={2,5,6,9,3,4,7,8,1,0};
ThreadTree T=(ThreadTree)malloc(sizeof(ThreadNode));
T->data=a[0];
T->lchild=T->rchild=NULL;
for(i=1;i<9;i++){
T=Creat(T,a[i]);
}
CreatPostThread(T);
printf("%d",PreNode(T)->data);
return 0;
}