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 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 二叉树的线索化及其遍历(前序和中序) -> 正文阅读

[数据结构与算法]二叉树的线索化及其遍历(前序和中序)

#include<iostream>
using namespace std;
enum Tag { link, thread };
typedef struct Bitree
{
	char sign;
	int data;
	Bitree* left;
	Bitree* right;
	Tag ltag;
	Tag rtag;
}bi_node;
void cre_tree(bi_node* &node);//注意引用,比二级指针更方便
//————————————————————————————
void pre_display(bi_node*);//前序遍历
void in_display(bi_node*);//中序遍历
void post_display(bi_node*);//后序遍历
//————————————————————————————
void pre_cueing(bi_node*);//前序线索化
void in_cueing(bi_node*);//中序线索化
//————————————————————————————
void pre_traversal(bi_node* node);//前序遍历线索树
void in_traversal(bi_node* node);//中序遍历线索树
//————————————————————————————
//注意这里的pre要全局呀!!
//********************
bi_node* pre;
int main()
{
	cout << "输入序列以创建二叉树:(如AB#D##C##)\n";
	
	char signs = getc(stdin);
	ungetc(signs, stdin);
	bi_node* tree = NULL;
	cre_tree(tree);
	cout << "二叉树创建成功!";
	cout << "\n前序遍历:" << endl;
	pre_display(tree);
	cout << "\n中序遍历:" << endl;
	in_display(tree);
	cout << "\n后序遍历:" << endl;
	post_display(tree);
	pre = NULL;
	pre_cueing(tree);
	cout << "\n先序线索化完成!" << endl;
	cout << "先序遍历线索化树:" << endl;
	pre_traversal(tree);
	cout << "\n创建一棵新二叉树:" << endl;//必须重新创建一棵树用来中序线索化,前一棵树已经被前序线索化了,不能再被中序线索化
	getchar();//吸取上一次的回车
	char new_signs = getchar();
	ungetc(new_signs, stdin);//把读取的第一个字符重新放入缓冲区首位置
	bi_node* new_tree = NULL;
	cre_tree(new_tree);
	pre = NULL;//注意这里pre重新设置
	in_cueing(new_tree);
	cout << "中序线索化完成!" << endl;
	cout << "中序遍历线索化树:" << endl;
	in_traversal(new_tree);

}
void cre_tree(bi_node* &node)//创建二叉树;
{
	char ch = getc(stdin);
	if (ch == '#')
	{
		node = NULL;//'#'代表此处为NULL
		return;
	}
	else
	{
		node = new bi_node;    //如果不为'#',则创捷新节点
		node->sign = ch;      
		node->ltag = node->rtag = link;//初始化节点,左右孩子都为link(因为此时没有加线索)
		cre_tree(node->left);  
		cre_tree(node->right);
	}
}

void pre_cueing(bi_node* node)//前序线索化思路不要与遍历前序线索化混淆
{                             //前序线索化的的节点经过顺序和建立二叉树的节点经过的顺序是相同的!!
	if (node == NULL)
		return;
	if (node->left == NULL)
	{
		node->ltag = thread;
		node->left = pre;
	}
	if (pre!=NULL && pre->right == NULL)//pre!=NULL是为了应付第一个节点,它的前驱节点是pre,而此时pre是NULL,不存在pre->right
	{
		pre->rtag = thread;           
		pre->right = node;
	}                                 
	//以上两个if内的操作:1.将本节点连上前驱  2.将前驱连上后继(即本节点)
	pre = node;//!!!
	if (node->ltag == link)//ltag为link才可进入!否则有可能再次进入前驱节点而陷入死循环!
		pre_cueing(node->left);
	if (node->rtag == link)//node->rtag一定是link,此if可删,不过为了统一,还是与上面对应
		pre_cueing(node->right);
	//若ltag和rtag都不是link,即左右孩子都不存在,则按照正常递归顺序进入到下一个节点(依次弹栈)
}
void in_cueing(bi_node* node)
{
	if (node == NULL)
		return;
	in_cueing(node->left);//递归到最左边的子树;
	if (node->left == NULL)
	{
		node->left = pre;
		node->ltag = thread;
	}
	if (pre != NULL && pre->right == NULL)
	{
		pre->rtag = thread;
		pre->right = node;
	}
	pre = node;

		in_cueing(node->right);
}

void pre_traversal(bi_node* node)//前序遍历线索二叉树
{
	while (node)
	{
		cout << node->sign;
		if (node->rtag == thread)//优先通过线索进入后继节点,不行再按递归顺序进行
			node = node->right;
		else if (node->left != NULL&&node->ltag!=thread)//务必不可忽略后半部分的条件!否则会在最后两个节点陷入死循环!可以把后半部分删掉试试;
			node = node->left;
		else
			node = node->right;  
	}
}
void in_traversal(bi_node* node)
{
	while (node)
	{
		while (node->left != NULL&&node->ltag==link)//node->left如非NULL,则既可能左孩子,也可能是左线索,如果是左孩子,则进入while
			node = node->left;     //一直向左下遍历,直到碰见第一个没有左孩子的节点(中序排第一)
		cout << node->sign;
		while (node->rtag == thread )//如果有有线索,直接跳到有线索指向的节点,并循环此步,直到没有右线索
		{
			node = node->right;
			cout << node->sign;
		}
		node = node->right;//否则,按照中序遍历的规律,找其右子树中最左下的结点,也就是继续循环遍历
	}
	//上面理解比较复杂,务必画图辅助理解!!!画一个特殊点的图,然后一步一步解决问题,就基本可行了;
}
void pre_display(bi_node* node)
{
	if (node == NULL)
		return;
	cout << node->sign;
	pre_display(node->left);
	pre_display(node->right);
}
void in_display(bi_node* node)
{
	if (node == NULL)
		return;
	in_display(node->left);
	cout << node->sign;
	in_display(node->right);
}
void post_display(bi_node* node)
{
	if (node == NULL)
		return;
	post_display(node->left);
	post_display(node->right);
	cout << node->sign;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-09 11:55:23  更:2021-12-09 11:56:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/10 2:32:22-

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