_DataStructure_C_Impl:线索二叉树

#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100
/*线索二叉树类型定义*/
typedef char DataType;
typedef enum {Link,Thread}PointerTag;//Link=0表示指向孩子节点,Thread=1表示指向前驱节点或后继节点
typedef struct Node{
	DataType data;
	struct Node *lchild,*rchild;	//指向左右孩子节点的指针
	PointerTag ltag,rtag;		//线索标志域
}BiThrNode;
typedef BiThrNode* BiThrTree;	//二叉树类型

BiThrTree pre;//pre始终指向已经线索化的结点
//利用括号嵌套的字符串建立二叉链表
void CreateBitTree2(BiThrTree *T,char str[]){
	char ch;
	BiThrTree stack[MaxSize];
	int top=-1;
	int flag,k;
	BiThrNode *p;
	*T=NULL;
	k=0;
	ch=str[k];
	while(ch!='\0'){
		switch(ch){
		case '(':
			stack[++top]=p;
			flag=1;
			break;	
		case ')':
			top--;
			break;
		case ',':
			flag=2;
			break;
		default:
			p=(BiThrTree)malloc(sizeof(BiThrNode));
			p->data=ch;
			p->lchild=NULL;
			p->rchild=NULL;

			if(*T==NULL)
				*T=p;
			else{
				switch(flag){
				case 1:
					stack[top]->lchild=p;
					break;
				case 2:
					stack[top]->rchild=p;
					break;
				}
				if(stack[top]->lchild)
					stack[top]->ltag=Link;
				if(stack[top]->rchild)
					stack[top]->rtag=Link;
			}
		}
		ch=str[++k];
	}
}
//二叉树中序线索化
void InThreading(BiThrTree p){
	if(p){
		InThreading(p->lchild);	//左子树线索化
		if(!p->lchild){		//前驱线索化
			p->ltag=Thread;
			p->lchild=pre;
		}
		if(!pre->rchild){	//后继线索化
			pre->rtag=Thread;
			pre->rchild=p;
		}
		pre=p;	//pre指向的结点线索化完毕,使p指向的结点成为前驱
		InThreading(p->rchild);	//右子树线索化
	}
}
//通过中序遍历二叉树T,使T中序线索化。Thrt是指向头结点的指针
int InOrderThreading(BiThrTree *Thrt,BiThrTree T){
	if(!(*Thrt=(BiThrTree)malloc(sizeof(BiThrNode))))	//为头结点分配内存单元
		exit(-1);
	//将头结点线索化
	(*Thrt)->ltag=Link;			//修改前驱线索标志
	(*Thrt)->rtag=Thread;		//修改后继线索标志
	(*Thrt)->rchild=*Thrt;		//将头结点的rchild指针指向自己
	if(!T)		//如果二叉树为空,则将lchild指针指向自己
		(*Thrt)->lchild=*Thrt;
	else{
		(*Thrt)->lchild=T;		//将头结点的左指针指向根结点
		pre=*Thrt;				//将pre指向已经线索化的结点
		InThreading(T);			//中序遍历进行中序线索化
		//将最后一个结点线索化
		pre->rchild=*Thrt;		//将最后一个结点的右指针指向头结点
		pre->rtag=Thread;		//修改最后一个结点的rtag标志域
		(*Thrt)->rchild=pre;	//将头结点的rchild指针指向最后一个结点
	}
	return 1;
}
//打印线索二叉树中的结点及线索
int Print(BiThrTree T){
	static int k=1;
	printf("%2d\t%s\t  %2c\t  %s\t\n",k++,T->ltag==0?"Link":"Thread",
		T->data,
		T->rtag==1?"Thread":"Link");
	return 1;
}
//中序遍历线索二叉树。其中visit是函数指针,指向访问结点的函数实现
int InOrderTraverse(BiThrTree T,int (* visit)(BiThrTree e)){
	BiThrTree p;
	p=T->lchild;		//p指向根结点
	while(p!=T){		//空树或遍历结束时,p==T
		while(p->ltag==Link)
			p=p->lchild;
		if(!visit(p))		//打印
			return 0;
		while(p->rtag==Thread&&p->rchild!=T){		//访问后继结点
			p=p->rchild;
			visit(p);
		}
		p=p->rchild;
	}
	return 1;
}
//在中序线索树中找结点*p的中序直接前趋
BiThrNode *InOrderPre(BiThrNode *p){
	BiThrNode *pre;
	if(p->ltag==Thread)		//如果p的标志域ltag为线索,则p的左子树结点即为前驱
		return p->lchild;
	else{
		pre=p->lchild;		//查找p的左孩子的最右下端结点
		while(pre->rtag==Link)		//右子树非空时,沿右链往下查找
			pre=pre->rchild;
		return pre;		//pre就是最右下端结点
	}
}
//在中序线索树中查找结点*p的中序直接后继
BiThrNode *InOrderPost(BiThrNode *p){
	BiThrNode *pre;
	if(p->rtag==Thread)		//如果p的标志域ltag为线索,则p的右子树结点即为后继
		return p->rchild;
	else{
		pre=p->rchild;		//查找p的右孩子的最左下端结点
		while(pre->ltag==Link)
			pre=pre->lchild;		//左子树非空时,沿左链往下查找
		return pre;		//pre就是最左下端结点
	}
}
//中序遍历线索二叉树,返回元素值为e的结点的指针
BiThrNode *FindPoint(BiThrTree T,DataType e){
	BiThrTree p;
	p=T->lchild;
	while(p!=T){
		while(p->ltag==Link)
			p=p->lchild;
		if(p->data==e)		//找到结点,返回指针
			return p;
		while(p->rtag==Thread&&p->rchild!=T){		//访问后继结点
			p=p->rchild;
			if(p->data==e)		//找到结点,返回指针
				return p;
		}
		p=p->rchild;
	}
	return NULL;
}
//销毁二叉树操作
void DestroyBitTree(BiThrTree *T){
	if(*T){		//如果是非空二叉树
		if((*T)->lchild)
			DestroyBitTree(&((*T)->lchild));
		if((*T)->rchild)
			DestroyBitTree(&((*T)->rchild));
		free(*T);
		*T=NULL;
	}
}
void main(){
	BiThrTree T,Thrt;
	BiThrNode *p,*pre,*post;
	CreateBitTree2(&T,"(A(B(,D(G)),C(E(,H),F))");
	printf("线索二叉树的输出序列:\n");
	InOrderThreading(&Thrt,T);
	printf("序列   前驱标志   结点  后继标志\n");
	InOrderTraverse(Thrt,Print);
	p=FindPoint(Thrt,'D');
	pre=InOrderPre(p);
	printf("元素D的中序直接前驱元素是:%c\n",pre->data);
	post=InOrderPost(p);
	printf("元素D的中序直接后继元素是:%c\n",post->data);
	p=FindPoint(Thrt,'E');
	pre=InOrderPre(p);
	printf("元素E的中序直接前驱元素是:%c\n",pre->data);
	post=InOrderPost(p);
	printf("元素E的中序直接后继元素是:%c\n",post->data);
	//DestroyBitTree(&Thrt);
	system("pause");
}

转载于:https://www.cnblogs.com/javafly/p/6037139.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值