IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> |/实现中序线索化二叉树 -> 正文阅读

[C++知识库]|/实现中序线索化二叉树

#include<malloc.h>
#include<stdlib.h>
#include<stdio.h>
#define	MaxSize 100

//实现中序线索化二叉树

typedef struct node{
	char data;		//数据域
	int ltag,rtag;	//线索标记
	struct node *lchild;	//左孩子指针
	struct node *rchild;	//右孩子 
}TBTNode;

//ltag、rtag为1:表示线索化 

//由str串建立含空线索域的二叉链b
void CreateTBTree(TBTNode *&b,char *str){
	TBTNode *St[MaxSize],*p;
	int top=-1,k,j=0;
	char ch=str[j];		//ch赋值为字符串的第一个字符
	b=NULL;		//初始化二叉树b 	
	while(ch!='\0'){		//扫描到结束符退出循环 
		switch(ch){
			case'(':
				top++;
				St[top] = p;	//St存储双亲结点 ,也就是上一个结点 
				k=1;		//k用于标记下个元素是不是左右孩子
				break;		//开始处理左子树
			case')':
				top--;		//删除一个St中的双亲元素 
				break;		//子树处理完毕
			case',':
				k=2;		//k=2,下个元素为右孩子 
				break;		//开始处理右子树	
			default:
				p=(TBTNode *)malloc(sizeof(TBTNode));
				p->data = ch;		//存储结点值 
				p->lchild = p->rchild = NULL;	//左右指针全指向NULL
				if (b==NULL)	
					b=p;	//若b为空,p置为二叉树根结点
							//这里修改了头指针,所以函数定义时,需要用&
							 
				else{		//若已经创建好根结点
					switch(k){		//这里用的k标记是上一轮循环标记好的 
						case 1:St[top]->lchild = p;		//St[top]存储了上一个结点p1
							//等价于 p1->lchild = p; 
								break;
						case 2: St[top]->rchild = p;
								break;
					} 
					
				} 
				 
		}
		j++;
		ch = str[j];
	}
	
} 

//输出含空线索域的二叉树 
void DispTBTree(TBTNode *b){
	if(b!=NULL){
		printf("%c",b->data);
		if(b->lchild != NULL || b->rchild != NULL){
			printf("(");	//有孩子结点时才输出(
			DispTBTree(b->lchild);	//递归处理左子树
			if(b->rchild != NULL)
				printf(",");		//有右孩子结点时才输出,
			DispTBTree(b->rchild);	// 递归处理右子树
			printf(")");	//有孩子结点时才输出)
		}
	}
}

TBTNode *pre;	//==========全局变量===================
 
//中序线索化二叉树,被CreateThread调用
void Thread(TBTNode *&p){
	if(p!=NULL){
		Thread(p->lchild);	//-------递归遍历左子树,并将其线索化 
		if(p->lchild == NULL){		//若左指针为空,将该指针作为线索保存前驱结点
			p->lchild = pre;	//p的前驱是pre,所以p的左孩子保存pre结点 
			p->ltag=1;		//标记该结点已经线索化 
		} else	//否则标记左指针不能被线索化
			p->ltag=0;
		if(pre->rchild == NULL)	{	//pre的后继是p,所以pre的右孩子保存p结点
		//注意此处判断的pre的右孩子是否为空  
			pre->rchild=p;
			pre->rtag=1; 
		}else
			pre->rtag=0;
		pre = p;	//修改前驱结点
		Thread(p->rchild);	//--------递归遍历右子树,并将其线索化 
	}
} 

//问题一:已经构建好了二叉树,并且在Thread中已经线索化了,那么CreateThread()函数有什么作用?
/*-------
作用一:增加一个头结点root,使得第一个被线索化的结点有前驱root; 
作用二: 修改全局变量pre,使它指向根结点root ;
作用三:Thread函数将数b线索化后,最后被遍历的结点的右指针并没有被线索化, 
		所以Thread调用完后,需将最后结点(线索化后pre指向最后一个结点)的右指针线索化 ,
		指向根结点root; 
----------*/ 

//创建中序线索化二叉树
TBTNode *CreateThread(TBTNode *b){
	TBTNode *root;
	root = (TBTNode *)malloc(sizeof(TBTNode));	//创建头结点
	root->ltag=0;	//左指针指向根结点 
	root->rtag=1;	//右指针用来线索化 
	root->rchild=b;//如果数b只有一个结点,那么头结点root的右指针指向最后一个结点 
	if(b==NULL)			//空二叉树 
		root->lchild = root; 
	else{
		root->lchild = b;
		pre = root;
		Thread(b);	
		pre->rchild = root;	//此时的pre为中序遍历的最后结点	
		pre->rtag = 1;
		root->rchild = pre; //将的右指针线索指向最后结点pre 
	}
	return root;
} 

// 被ThInOrder算法调用
void InOrder(TBTNode *tb){
	if(tb->lchild != NULL && tb->ltag == 0)		//有左孩子且没有被线索化
		InOrder(tb->lchild);
	printf("%c",tb->data);
	if(tb->rchild!=NULL && tb->rtag == 0)
		InOrder(tb->rchild); 
} 

//中序线索二叉树的中序遍历递归算法
void ThInorder(TBTNode *tb){
	InOrder(tb->lchild);
} 

//中序线索二叉树的中序遍历非递归算法
void ThInOrder1(TBTNode *tb){
	TBTNode *p = tb->lchild;	//指向根结点
	while(p!=tb){
		while(p->ltag == 0)		//找中序开始结点 
			p=p->lchild;
		printf("%c",p->data);
		while(p->rtag == 1 && p->rchild != tb){
			p=p->rchild;
			printf("%c",p->data);
		}
		p=p->rchild;
		
	} 
}

//被DestroyTBTree算法调用

void DestroyTBTree1(TBTNode *tb){
	if(tb!=NULL){
		if(tb->lchild != NULL && tb->ltag == 0)	//如果有左孩子,且没被线索化
			DestroyTBTree1(tb->lchild);
		if(tb->rchild != NULL && tb->rtag == 0)
			DestroyTBTree1(tb->rchild);
		free(tb); 
	}
} 

//释放中序线索二叉树的所有结点
void  DestroyTBTree(TBTNode * tb){
	DestroyTBTree1(tb->lchild);
	free(tb);
	printf("释放完成");
}

int main(){
	TBTNode *b,*tb;
	CreateTBTree(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I))");
	printf("二叉树:");DispTBTree(b);printf("\n");
	tb=CreateThread(b);
	tb=b;
	printf("线索中序序列:\n");
	printf("  递归算法:");ThInorder(tb); printf("\n");
	printf(" 非递归算法:");ThInOrder1(tb);printf("\n");
	DestroyTBTree(tb);
	return 1;
}







 


 

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-16 11:12:18  更:2022-05-16 11:12:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 18:35:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码