线索二叉树


//2013.7.4
//对线索二叉树有了更深入的理解。过去学习数据结构更注重代码实现。

//现在则更注重对算法思想的理解。因为只要有了思路,代码实现都没有问题(只要有一定程序调试能力)。

//至于线索二叉树以前只注意到线索二字。然而线索终究是给出一定指示即可,是不需要从头指向尾的。

//从头指向尾也没问题,但,二叉树只有左右两个指针。一个根节点如果有两个子节点的话。

//便没有多余的结点来供它来做线索来指向了!

//所以线索也只是对遍历的一种配合,中序线索二叉树,先让其走向最左端,然后按线索走向中间。

//然后再走向右端。



//-------------------二叉树的二叉树线索存储表示----------
typedef enum PointerTag  { Link, Thread };            //Link == 0; 指针,Thread == 1;线索
typedef struct BiThrNode {
	TElemType        data;
	struct BiThrNode  *lchild,  *rchild;                      //左右孩子指针
	PointerTag         LTag, RTag;                             //左右标志
}BiThrNode,  *BiThrTree;

Status InOrderTraverse_Thr(BiThrTree T, Status(*Visit)(TElemType e)){
      //T指向头结点,头结点的左链lchild指向根结点。
	 //中序遍历二叉树线索树T的非递归算法,对每个数据元素调用函数Visit
	p = T -> lchild;                                             //p指向根节点
	while (p != T){                                            //空树或遍历结束时,p == T
		while (p -> LTag == Link) p = p -> lchild;
		if (!Visit(p -> data)) return ERROR;             //访问其右子树为空的结点
		while (p -> RTag == Thread && p -> rchild != T) {
			p = p -> rchild;      Visit(p -> data);       //访问后继结点
		}
		p = p -> rchild;
	}
	return OK;
}

Status InOrderThreading (BinThrTree &Thrt, BiThrTree T) {
	 //中序遍历二叉树T,并将其中序线索化,Thrt指向头结点
	if(!(Thrt = (BiThrTree)malloc(sizeof(BiThrNode))))exit(OVERFLOW);
	Thrt -> LTag = Link;   Thrt -> Rtag = Thread;         //建立头结点
	Thrt -> rchild = Thrt;                                          //右指针回指
	if(!T)  Thrt -> lchild = Thrt;                                 //若二叉树空,则左指针回指
	else{
		Thrt -> lchild = T;   pre = Thrt;
		InThreading(T);                                             //中序遍历进行中序线索化
		pre -> rchild = Thrt;  pre -> RTag = Thread;      //最后一个结点线索化
		Thrt -> rchild = pre;                                     
	}
	return OK;
}

void InThreading(BinThree b) {
	if(p) {
		InThreading(p -> lchild);                               //左子树线索化
	     if(!p -> lchild) {p -> LTag = Thread; p -> lchild = pre; }//前驱线索
		if(!p -> rchild) {pre -> RTag = Thread; pre -> rchild = p;}  //后继线索化
		pre =p;                                                   //保持pre指向p的前驱
		InThreading(p -> rchild);                             //右子树线索化
	}
}




//2013.2.23

#include <stdio.h>
#include<malloc.h>
#define LEN sizeof(struct ThreadBinTree)
#define NULL 0
enum NodeFlag
{
	SubTree,
	Thread
};                                                                //枚举值SubTree和Thread分别为0,1
struct ThreadBinTree
{
	int data;                                                  //元素数据
	NodeFlag lflag;                                          //左标志
	NodeFlag rflag;                                          //右标志
	struct ThreadBinTree *left;                                 //左子树结点指针
	struct ThreadBinTree *right;                               //右子树结点指针
};
ThreadBinTree *Previous;
void BinTreeThreading_LDR(ThreadBinTree *bt)                //二叉树按中序线索化
{
	if(bt)
	{
		BinTreeThreading_LDR(bt->left);                          //递归调用,将左子树线索化
		bt->lflag=(bt->left)?SubTree:Thread;                //设置左指针域的标志
		bt->rflag=(bt->right)?SubTree:Thread;                  //设置右指针域的标志
		if(Previous)                                            //若当前结点的前驱Previous存在
		{
			if(Previous->rflag==Thread)                 //若当前结点的前驱右标志为线索
				Previous->right=bt;                         //设Previous的右线索指向后继
			if(bt->lflag==Thread)                         //若当前结点的左标志为线索
				bt->left=Previous;                          //设当前结点的左线索指向中序前驱
		}
		Previous=bt;                                            //让Previous保存刚访问的结点
		BinTreeThreading_LDR(bt->right);                //递归调用将右子树线索化
	}
}
ThreadBinTree *BinTreeNext_LDR(ThreadBinTree *bt)           //求指定结点的后继
{
	ThreadBinTree *nextnode;
	if(!bt)
		return NULL;
	if(bt->rflag==Thread)                                       //若当前结点的右子树为空
		return bt->right;                                         //返回右线索所指的中序后继
	else
	{
		nextnode=bt->right;                                     //从当前1结点的右子树开始查找
		while(nextnode->lflag==SubTree)                  //循环处理所有左子树不为空的结点
			nextnode=nextnode->left;
		return nextnode;                                          //返回左下方的结点
	}
}
ThreadBinTree *BinTreePrevious_LDR(ThreadBinTree *bt)      //求指定结点的前驱
{
	ThreadBinTree *prenode;
	if(!bt)
		return NULL;                                              
	if(bt->lflag==Thread)                                      //若当前解结点的左子树为空
		return bt->left;                                         //返回左线索所指的中序后继
	else
	{
		prenode=bt->left;                                      //从当前结点的左子树开始查找
		while(prenode->rflag==SubTree)                 //循环处理所有右子树不为空的结点
			prenode=prenode->left;                
		return prenode;                                          //返回左下方结点
	}
}
void ThreadBinTree_LDR(ThreadBinTree *bt)
{
	if(bt)
	{
		while(bt->lflag==SubTree)                          //有左子树
			bt=bt->left;                                          //从根往下找最左下结点
		do
		{
			printf("%d",bt->data);                                   //处理结点
			bt=BinTreeNext_LDR(bt);                                  //找中序后继结点
		}while(bt);
	}
}
/*函数功能初始化一个二叉树,建立根节点。*/
ThreadBinTree *InitRoot()
{
	ThreadBinTree *node;
      node=(struct ThreadBinTree*)malloc(LEN);
	printf("请输入根节点的值:");
	scanf("%d",&node->data);
	node->left=NULL;
	node->right=NULL;
	return node;
}
/*函数功能:进行查找操作。*/
ThreadBinTree *BinTreeFind(ThreadBinTree *bt,int data)            //在二叉树中查找值为data的结点。
{
	ThreadBinTree *p;
	if(bt==NULL)
	return NULL;
	else
	{
		if(bt->data==data)
		return bt;
		else{
			if(p=BinTreeFind(bt->left,data))
				return p;
		     else if(p=BinTreeFind(bt->right,data))
			     return p;
		     else
			     return NULL;
	      }
	}
}
/*添加数据到二叉树*/
int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n)
{
	if(bt==NULL)
	{
		printf("\n父结点不在,请先设置父结点。");
		return 0;
	}
	switch(n)
	{
		case 1:
			if(bt->left)
			{
				printf("左子树结点不为空。");
				return 0;
			}
			else
				bt->left=node;
			break;
		case 2:
			if(bt->right)
			{
				printf("右子树结点不为空。");
				return 0;
			}
			else
				bt->right=node;
			break;
			default:
				printf("参数错误!\n");
			return 0; 
	}
	return 1;
}
/*函数功能:添加结点到二叉树。*/
void AddNode(ThreadBinTree *bt)
{
	int data;
	int select;
	ThreadBinTree *node,*parent;
     node=(struct ThreadBinTree*)malloc(LEN);
	printf("\n输入二叉树结点数据");
	scanf("%d",&node->data);
	node->left=NULL;
	node->right=NULL;
	printf("\n输入父结点数据:");
	scanf("%d",&data);
	parent=BinTreeFind(bt,data);
	if(!parent)
	{
		printf("\n未找到父结点。");
	}
	printf("\n1.添加到左子树\n2.添加到右子树\n");
	do{
		scanf("%d",&select);
		if(select==1||select==2)
		BinTreeAddNode(parent,node,select);
		}while(select!=1&&select!=2);
}
int main()
{
	ThreadBinTree *root=NULL;
	int select;
	do
	{
		printf("\n1.设置二叉树根元素\n2.添加二叉树根节点\n3.生成中序线索二叉树\n4.遍历线索二叉树\n0.退出");
		scanf("%d",&select);
		switch(select)
		{
			case 1:
				root=InitRoot();
			     break;
			case 2:
				AddNode(root);
			     break;
			case 3:
				BinTreeThreading_LDR(root);
			     printf("生成线索二叉树完毕");
			     break;
			case 4:
				printf("\n中序线索二叉树遍历的结果");
			     ThreadBinTree_LDR(root);
			      break;
			case 0:
				break;
		}
	}while(select!=0);
	return 0;
}
	




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值