线索二叉树(建立与遍历)

 线索二叉树的建立很需要思维能力,尽量把原理弄懂在去查看代码。

二叉树线索化
        二叉树的遍历是按照一定的规则把二叉树中的节点按照一定的次序排列成线性序列进行访问的,实质上就是对一个非线性结构进行线索化操作,使得每个节点(除第一个和最后一个外)都有前驱和后继节点,有时为了运算方便需要记录这些前驱和后继节点,称为二叉树线索化,而对于不同的遍历规则,又分为先序线索二叉树,中序线索二叉树(常用),后序线索二叉树。

思路:

        一颗具有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的这位博主的文字,而且我看了一下他的图片也很清晰(我不会画图.......)。如果觉得本人写的不好可以去这位博主的主页观看。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值