线索二叉树

线索二叉树的定义:(摘自数据结构自考网http://student.zjzk.cn/course_ware/data_structure/web/shu/shu6.4.1.htm)

n个结点的二叉链表中含有n+1个空指针域。利用二叉链表中的空指针域,存放指向结点在某种遍历次序下的前趋和后继结点的指针(这种附加的指针称为"线索")。

为了区分这个指针是指向前驱(或后继)还是指向孩子节点的,我们需要加上标志 lTag,rTag 来区分

这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(ThreadedBinaryTree)。

根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种。


因为线索二叉树保存了每个节点的前去后继信心,对于需要频繁查询树中节点的前驱,后继的情况,线索二叉树是个不错的选择


Code:(转自http://www.cppblog.com/goal00001111/articles/7359.html)

#include<stdio.h>
#include<malloc.h>

typedef struct ThreadBiTreeNode
{
	char data;
	struct ThreadBiTreeNode *lChild;
	struct ThreadBiTreeNode *rChild;
	int lTag,rTag;
}BiTNode,*BiTree;

void CreateBTree(BiTree &biTree){
	char data;
	data = getchar();
	if(data=='0'){
		biTree = NULL;
	}
	else {
		biTree = (BiTree)malloc(sizeof(BiTNode));
		biTree->data = data;
		CreateBTree(biTree->lChild);
		CreateBTree(biTree->rChild);
	}
}

void InOrder(BiTree biTree){
	if(biTree != NULL){
		InOrder(biTree->lChild);
		printf("%c ",biTree->data);
		InOrder(biTree->rChild);
	}return ;
}

void InThreading(BiTree & p,BiTree & pre)
{
	if(p){
		InThreading(p->lChild,pre);
		
		if(!p->lChild){	//左孩子空,左孩子指针指向前驱
			p->lTag=1;
			p->lChild=pre;
		}
		else p->lTag=0;
		
		if(pre && !pre->rChild){	//前驱 的 右孩子空,前驱的右孩子指针指向后继
			pre->rTag=1;
			pre->rChild=p;
		}
		
		pre = p;
		pre->rTag = 0;
		
		InThreading(p->rChild,pre);
	}
}

BiTree InOrderThreading(BiTree biTree)
{
	BiTree threadTree = new BiTNode;
	//新加的节点(头节点),树中没有这个点
	//中序线索化出的链表的第一个节点的前驱(左孩子指针)指向这个 头节点,
	//同时链表最后一个节点的后继(右孩子指针)也指向这个 头结点,
	//而这个 头结点的 左孩子指针 指向二叉树的根节点,右孩子指针 指向中序线索化链表的最后一个节点
	//类似双向链表

	threadTree->lTag = 0;	//没有左孩子
	threadTree->rTag = 1;	//有右孩子
	threadTree->rChild = threadTree;	//右指针回指
	
	if(!biTree){//空树 左指针 回指
		threadTree->lChild = threadTree;
	}
	else {
		threadTree->lChild = biTree;
		BiTree pre = threadTree;
		InThreading(biTree,pre);//中序线索化
		
		pre->rChild = threadTree;
		pre->rTag = 1;
		threadTree->rChild = pre;
	}
	return threadTree;
}

void InOrderTraverse_Thr(BiTree biTree)//中序遍历线索二杈树的非递归算法, biTree 指向头结点
{
	BiTree p = biTree->lChild; //p指向根结点
	while (p != biTree) //空树或遍历结束时,p == biTree
	{
		//从根开始寻找第一个结点,中根序列第一个节点是没有左孩子的,也就是lTag = 0
		//这点是区分 中序线索化 的标志,同样的,其它的线索化也都根据相应的特点来做
		while (p->lTag == 0)
		{
			p = p->lChild;
		}
		printf("%c ",p->data);
		
		while (p->rTag == 1 && p->rChild != biTree)//访问后继结点
		{
			p = p->rChild;
			printf("%c ",p->data);
		}
		p = p->rChild;
	}
}

BiTree NewBTree(char x)//构造一个数据域为x的新结点
{
	BiTree s = new BiTNode;
	s->data = x;
	s->lChild = s->rChild = NULL;
	s->lTag = s->rTag = 0;
	return s;
}

void Insert(BiTree & b, BiTree s)//在二杈排序树中插入新结点s
{
	if (b == NULL)
		b = s;
	//else if(b->data == s->data)//不做任何插入操作
	//	return;
	else if(b->data > s->data)//把s所指结点插入到左子树中
		Insert(b->lChild, s);
	else					//把s所指结点插入到右子树中
		Insert(b->rChild, s);
}

int main()
{
	BiTree biTree=NULL;
	//puts("Input:12300400500");  
    puts("Input:ABD000CE00F00");   
    /********************* 
			A
			
		/       \
		
		B       C
		
	/		/		\       

	D		E		F
	*********************/  
    CreateBTree(biTree);
	
    puts("中根遍历二叉树(递归):");  
    InOrder(biTree);puts("");  
    puts("");
	
	BiTree BT = InOrderThreading(biTree);
	
	puts("中根遍历线索二叉树(非递归):");
	InOrderTraverse_Thr(BT);puts("");
	
	return 0;
}


你可能感兴趣的:(数据结构,struct,null,input,insert,BT)