栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

线索二叉树C++代码及线索化过程详解

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

线索二叉树C++代码及线索化过程详解

文章目录
  • 线索二叉树的概念
  • 中序线索二叉树的构造
  • 中序线索二叉树的遍历
  • 过程详解版代码
  • 纯享版代码

我在这里不仅写了线索二叉树的普通代码,在代码中我还加入了线索化过程的打印,更好的帮助理解!

线索二叉树的概念

传统的二叉树存在很多空指针,能否利用这些空指针来存放指向其前驱或后继的指针?这样就可以像遍历单链表那样方便地遍历二叉树。引入线索二叉树正是为了加快查找结点前驱和后继的速度。
若无左子树,令lchild指向其前驱结点;若无右子树,令rchild指向其后继结点。如图所示,还需增加两个标志域标识指针域是指向左(右)孩子还是指向前驱(后继)。 这就是线索二叉树

中序线索二叉树的构造

二叉树的线索化是将二叉链表中的空指针改为指向前驱或后继的线索。而前驱或后继的信息只有在遍历时才能得到,因此线索化的实质就是遍历一次二叉树。
以中序线索二叉树的建立为例。附设指针 pre 指向刚刚访问过的结点,指针p 指向正在访问的结点,即pre指向p 的前驱。在中序遍历的过程中,检查p的左指针是否为空,若为空就将它指向pre;检查pre的右指针是否为空,若为空就将它指向p,如图所示。

中序线索二叉树的遍历

中序线索二叉树的结点中隐含了线索二叉树的前驱和后继信息。在对其进行遍历时,只要先找到序列中的第一个结点,然后依次找结点的后继,直至其后继为空。在中序线索二叉树中找结点后继的规律是:若其右标志为“1”,则右链为线索,指示其后继,否则遍历右子树中第一个访问的结点(右子树中最左下的结点)为其后继。


过程详解版代码

程序运行部分结果:

代码:

#include
#include
#include
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -1

#define TElemType char
#define Status int


typedef enum {Link, Thread} PointerTag;	//子树不为空时,Link==0 表示指针;子树为空时,Thread==1表示线索
typedef struct BiThrNode{
	TElemType data;
	struct BiThrNode *lchild, *rchild;	//左右孩子 
	PointerTag LTag, RTag;				//左右标志 
}BiThrNode, *BiThrTree; 

int cnt = 0;


Status CreatBiThrTree(BiThrTree &T){
	//按照先序序列输入二叉树中结点的值(一个字符),#表示空树
	char ch;
	cin >> ch;
	if(ch == '#') T = NULL;
	else{
		if(!(T = (BiThrNode*)malloc(sizeof(BiThrTree)))) exit(OVERFLOW);
		T->data = ch;				//生成根节点 
		T->LTag = Link;
		T->RTag = Link;
		CreatBiThrTree(T->lchild);	//构造左子树 
		CreatBiThrTree(T->rchild);	//构造右子树 
	}
	return OK; 
}//CreatBiThrTree


void Visualize(BiThrTree p, BiThrTree pre){
	//线索化的可视化输出
	cout << "p指向的结点:";
	if(p != NULL) cout << p->data << 't';
	else cout << "NULLt";
	cout <<  "pre指向的结点:";
	if(pre != NULL) cout << pre->data << endl;
	else cout << "NULL" << endl; 
}
Status InThread(BiThrTree &p, BiThrTree &pre){
	Visualize(p, pre);
	if(p != NULL){
		cout << "------------------------------------>线索化" << p->data << "的左子树" << endl; 
		InThread(p->lchild, pre);	//递归,线索化左子树
		cout << "------------------------------------>" << p->data << "的左子树线索化完成" << 't';
		if(p->lchild == NULL){		//如果左子树为空,建立前驱线索
			cout << p->data << "的前驱节点指向pre指向的结点" << endl; 
			p->lchild = pre;
			p->LTag = Thread;		
		}
		if(pre != NULL && pre->rchild == NULL){
			cout << pre->data << "的后继结点指向" << p->data << endl;
			pre->rchild = p;		//如果此时的前驱结点的右子树为空,建立后继线索 
			pre->RTag = Thread;
		}
		cout << "pre指向p所指向的结点" << endl;
		pre = p;					//pre后移
		cout << "------------------------------------>线索化" << p->data << "的右子树" << endl; 
		InThread(p->rchild, pre);	//递归,线索化右子树 
		cout << "------------------------------------>" << p->data << "的右子树线索化完成" << endl;
		cout << ++cnt << "次线索化之后:"; 
		Visualize(p, pre);
		cout << endl << endl; 
	}//else if(p == NULL) return ERROR;//空树返回错误 
	return OK;
}//InThread
Status CreatInThread(BiThrTree &T){
	BiThrTree pre = NULL;	//因为第一个结点一开始无前驱
	if(T != NULL){
		InThread(T, pre);	//线索化二叉树
		pre->rchild = NULL;	//处理到了最后一个结点,pre指向最后一个结点,右孩子设为空表示最后一个结点 
		pre->RTag = Thread; //表示指针 
	}
	return OK;
}//CreatInThread


void visit(BiThrNode *p){
	cout << p->data;
}


void InOrder(BiThrTree T){
	if(T != NULL){
		InOrder(T->lchild);
		visit(T);
		InOrder(T->rchild);
	}
}


BiThrNode *FirstNode(BiThrNode *p){
	//求中序线索二叉树中中序序列下的第一个结点
	while(p->LTag != Thread) p = p->lchild;	//找到最左下方的结点(中序的第一个结点)
	return p; 
}
BiThrNode *NextNode(BiThrNode *p){
	//求中序线索二叉树中结点p在中序序列的后继结点
	if(p->RTag == Link) 
		return FirstNode(p->rchild);		//如果有右子树,继续递归向下找 
	else return p->rchild;					//RTag==1,直接返回线索 
}
void InThreadOrder(BiThrTree T){
	//不含头结点的中序线索二叉树的中序遍历算法 
	for(BiThrNode *p = FirstNode(T); p != NULL; p = NextNode(p))
		visit(p);
}


int main(){
	cout << "---------------这是一个线索二叉树程序!---------------" << endl;
	cout << "-------------首先按照先序序列建立一棵线索二叉树-------" << endl << endl;
	cout << "按照先序序列输入二叉树中结点的值(一个字符),#表示空树" << endl;	
	BiThrTree T;
	CreatBiThrTree(T);
	cout << "二叉树的递归中序遍历:"; 
	InOrder(T);
	
//	if(s == 1) 
	cout << endl << endl << "-------------下面进行中序线索化-------------" << endl;
	cout << "--------------打印线索化的过程--------------" << endl;
	
	
	if(CreatInThread(T) == 1) cout << "--------------已完成线索化--------------" << endl;
	cout << "中序线索二叉树的非递归遍历序列:";
	InThreadOrder(T);
	
	return 0;
}
//测试示例:abc##de#g##f###
纯享版代码
#include
#include
#include
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -1

#define TElemType char
#define Status int


typedef enum {Link, Thread} PointerTag;	//子树不为空时,Link==0 表示指针;子树为空时,Thread==1表示线索
typedef struct BiThrNode{
	TElemType data;
	struct BiThrNode *lchild, *rchild;	//左右孩子 
	PointerTag LTag, RTag;				//左右标志 
}BiThrNode, *BiThrTree; 


Status CreatBiThrTree(BiThrTree &T){
	//按照先序序列输入二叉树中结点的值(一个字符),#表示空树
	char ch;
	cin >> ch;
	if(ch == '#') T = NULL;
	else{
		if(!(T = (BiThrNode*)malloc(sizeof(BiThrTree)))) exit(OVERFLOW);
		T->data = ch;				//生成根节点 
		T->LTag = Link;				//这里一定要加上,不然后边会出错 
		T->RTag = Link;
		CreatBiThrTree(T->lchild);	//构造左子树 
		CreatBiThrTree(T->rchild);	//构造右子树 
	}
	return OK; 
}//CreatBiThrTree


Status InThread(BiThrTree &p, BiThrTree &pre){
	if(p != NULL){
		InThread(p->lchild, pre);	//递归,线索化左子树
		if(p->lchild == NULL){		//如果左子树为空,建立前驱线索
			p->lchild = pre;
			p->LTag = Thread;		
		}
		if(pre != NULL && pre->rchild == NULL){
			pre->rchild = p;		//如果此时的前驱结点的右子树为空,建立后继线索 
			pre->RTag = Thread;
		}
		pre = p;					//pre后移
		InThread(p->rchild, pre);	//递归,线索化右子树 
	}//else if(p == NULL) return ERROR;//空树返回错误 
	return OK;
}//InThread
Status CreatInThread(BiThrTree &T){
	BiThrTree pre = NULL;	//因为第一个结点一开始无前驱
	if(T != NULL){
		InThread(T, pre);	//线索化二叉树
		pre->rchild = NULL;	//处理到了最后一个结点,pre指向最后一个结点,右孩子设为空表示最后一个结点 
		pre->RTag = Thread; 		//表示指针 
	}
	return OK;
}//CreatInThread


void visit(BiThrNode *p){
	cout << p->data;
}


void InOrder(BiThrTree T){
	if(T != NULL){
		InOrder(T->lchild);
		visit(T);
		InOrder(T->rchild);
	}
}


BiThrNode *FirstNode(BiThrNode *p){
	//求中序线索二叉树中中序序列下的第一个结点
	while(p->LTag != Thread) p = p->lchild;	//找到最左下方的结点(中序的第一个结点)
	return p; 
}
BiThrNode *NextNode(BiThrNode *p){
	//求中序线索二叉树中结点p在中序序列的后继结点
	if(p->RTag == Link) 
		return FirstNode(p->rchild);				//如果有右子树,继续递归向下找 
	else return p->rchild;					//RTag==1,直接返回线索 
}
void InThreadOrder(BiThrTree T){
	//不含头结点的中序线索二叉树的中序遍历算法 
	for(BiThrNode *p = FirstNode(T); p != NULL; p = NextNode(p))
		visit(p);
}


int main(){
	BiThrTree T;
	CreatBiThrTree(T);
//	InOrder(T);	
	CreatInThread(T);
	cout << "遍历序列:"; 
	InThreadOrder(T);	
	return 0;
}
//abc##de#g##f###
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/925760.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号