23线索二叉树:中序线索二叉树的遍历&&以及线索二叉树详细总结归纳整理

T   m这道题卡了我好几天 真 T   m心情非常烦躁哈 看CSDN上 那些人写的代码 写的不清不楚  你tama能不能写详细点啊 伪代码真的很恶心好吧?

感谢中序线索化二叉树及遍历 - 百度文库

带来的部分代码 好不容易看见的好代码

还有那个严蔚敏的书 写的是什么乱七八糟的东西 细节也不交代清楚 看的我真的恶心死了 cao

tama最后还不是得自己来写 真tm  zhizhang 连教学用书都写不好 详细点会死吗?Gross!你写不好我看nm的书呢?

首先给大家讲一下 我写代码关于空指针和野指针的问题

#include<iostream>
using namespace std;
struct student
{
student *p;
student *q;
}


int main()
{

    student* m;
if(m)
    {
        cout<<"1";
    }
else if(m==NULL)
    {
        cout<<"2";
    }

    student *i=new student
if(i)
    {
        cout<<"3";
    }
else if(i==NULL)
    {
        cout<<"4";
    }

return 0;

}

大家先要明白这个野指针初始化的问题。上述代码 m如果没有new student的话 会报错所以输出不了

而 i 进行了new student 所以可以 但只能输出3 i指针默认不是NULL所以不会输出4

最后结果 这段代码 只会输出 :3

然后我要讲一下线索化二叉树的思路

线索化二叉树的步骤是什么,像现在给大家归纳一下。(耐心看完)

  1. 首先你要用先序遍历或者其他遍历方式创建一颗普通的二叉树
  2. 然后你要对这个普通的二叉树进行线索化 线索化有两种方式 一种是带头结点 一种是不带头结点的
  3. 线索化后 这就是一颗线索二叉树了 
  4. 然后你就可以用特定的遍历方法----遍历中序线索二叉树  来对这个二叉树进行遍历并同时输出
  5. 注意 对普通二叉树的中序遍历输出结果 和 线索化这颗二叉树后在对其进行遍历中序线索二叉树  二者的输出结果是等效的。 

总结:

建立普通二叉树--->带头结点线索化或者直接无头结点线索化----->中序遍历线索二叉树---->结果一

建立普通二叉树-->中序遍历普通二叉树--->结果二

结果一和结果二一模一样。

这次我采用的是不带头节点的建立线索二叉树。

函数板块主要有 建立树 线索化  遍历输出

其中线索化 书上写的不清不楚的

 你所谓的全局变量初始化 你能不能写完写详细一点  ?

你如果直接在全局区域写一个 student*pre;后面运行的时候是会报错的!!!!!!!!!

有很多博客 就直接给你在全局区域这样写 student*pre错错错错!!!

你要实体化student *pre=new student(对对对!)才行,这tama才叫初始化!  写得不清不楚的真的口区。

 还有我画五角星那一段 很明显就有问题    !pre->rchild 

如果pre刚开始是空指针要怎么办?直接就报错了!

正确的 代码我放在下面 大家自己对比一下

void clue_tree(student *p)
{
	if (p)
	{
		clue_tree(p->left);

		if (p->left==NULL)//左孩子为空链接前驱
		{
			p->left = pre;
			p->tagleft = 1;
		}
		
		if (pre!=NULL&&pre->right==NULL)//pre右孩子为空链接后驱
		{
			pre->right = p;
			pre->tagright = 1;
		}
	
		pre = p;
		if (p->tagright == 0 && p->right == NULL)
		{
			p->tagright = 1;
		}

		clue_tree(p->right);
	}


}

然后再和大家强调一下,书上这个中序遍历 是带头节点的中序遍历   一定看清楚。

我接下来写的是不带头节点的遍历   

如果你线索化的时候用的是不带头结点的线索化 那书上这个遍历方式就会报错

     接下来我们用例题来实验一下  

23 线索二叉树:中序线索二叉树的遍历

作者: 冯向阳时间限制: 1S章节: DS:树

截止日期: 2022-06-30 23:55:00

问题描述 :

目的:使用C++模板设计中序线索二叉树的抽象数据类型(ADT)。并在此基础上,使用中序线索二叉树ADT的基本操作,设计并实现简单应用的算法设计。

内容:(1)请参照二叉树的ADT模板,设计中序线索二叉树的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考教材、课件,以及网盘中的链表ADT原型文件,自行设计二叉树的ADT。)

(2)ADT的简单应用:使用该ADT设计并实现若干遍历线索二叉树的算法设计。

应用:要求设计一个算法,对建立的中序线索二叉树进行遍历。

提示:中序遍历线索二叉树,首先找到第一个访问的结点,即最左下结点,然后通过查找后继结点的方法进行遍历。

参考函数原型:

中序线索二叉树的遍历(共有成员函数)

//中序线索二叉树的遍历  

template<class ElemType>

void Thread_BinaryTree<ElemType>::InThreading_Traverse(Thread_BinaryTreeNode<ElemType> *root, bool (*visit)(Thread_BinaryTreeNode<ElemType> *root));

输入说明 :

第一行:表示无孩子或指针为空的特殊分隔符

第二行:二叉树的先序序列(结点元素之间以空格分隔)

输出说明 :

第一行:中序线索二叉树的遍历结果

输入范例 :

#
A B # C D # # E # # F # G # H # #

输出范例 :

B(1,0),D(1,1),C(0,0),E(1,1),A(0,0),F(1,0),G(1,0),H(1,1)

student* find_next(student* & p)

void clue_tree(student *p) 

两个难点函数 好好理解

注意看清楚 全局变量pre是怎么初始化的!!!

#include<iostream>
#include<stack>
using namespace std;
int m = 1;

struct student
{
	string data;
	student* left;
	student* right;
	int tagleft=0;
	int tagright=0;
};

//先序建立二叉树
void creat(student*& T, string kk)
{
	string ch;
	cin >> ch;
	if (ch == kk)
	{
		T = NULL;
	}//但凡输入了#号 该节点下一位停止
	else
	{
		T = new student;
		T->data = ch;
		creat(T->left, kk);
		creat(T->right, kk);
	}
}

//二叉树的线索化 重点函数0号
student* pre = new student;//这才是正确的初始化 严老师你看清楚
void clue_tree(student *p)
{
	if (p)
	{
		clue_tree(p->left);

		if (p->left==NULL)//左孩子为空链接前驱
		{
			p->left = pre;
			p->tagleft = 1;
		}
		
		if (pre!=NULL&&pre->right==NULL)//pre右孩子为空链接后驱
		{
			pre->right = p;
			pre->tagright = 1;
		}
	
		pre = p;
		if (p->tagright == 0 && p->right == NULL)
		{
			p->tagright = 1;
		}//这段是我自己加的 用来保证最后一个元素的tagright为1  否则它会默认是0 不满足该题 要求 
		//比如ABCD   A的tagleft=1 虽然左边没有元素 但是仍有线索 线索指向NULL
		//同理 D后面虽然已经没有元素了 但仍有线索 线索指向NULL 如果没有这段代码 d的tagright默认=0;
		clue_tree(p->right);
	}


}







//重点函数1  找到后面一个应该输出元素 列如输出顺序是 ABCDEF 不管这个二叉树什么样子  B后面就是C  C后面就是D   
student* find_next(student* & p)
{
	student* next=NULL;
	student* q;
	if (p->tagright == 1)
	{
		next = p->right;//直接利用我们的线索 因为tag=1的时候 right就直接链接我们的后驱
	}
	else if (p->tagright == 0)//没有线索
	{
		if (p->right == NULL)
		{
			next = NULL;
		}
	   else if (p->right != NULL)//
		{

			q = p->right;
			while (q->tagleft == 0)
			{
				q = q->left;
			}
			next = q;
		}
		
	}
	return next;//如果这里的p指的是是C的话 这里返回的next 指的就是D
}


//重点函数2找到 中序遍历应该输出的头一个元素
student* find_the_first_student(student *& root)
{
	student* q = root;
	if (q)
	{
		while (q->left!=NULL)
		{
			q = q->left;
		}
	}
	return q;
	
}


//重点函数3    函数1 2仅在其中被利用
void display_the_tree(student *&root)
{
	student* p;
	p = find_the_first_student(root);
	while (p != NULL)
	{
		//
		if (m == 0)
		{
			cout << ",";
		}
		m = 0;
		cout << p->data;
		cout << "(";
		cout << p->tagleft;
		cout << ",";
		cout << p->tagright;
		cout << ")";
		//上述代码用来输出 m用来控制逗号
		
		p = find_next(p);
	}
}

int main()
{

	pre = NULL;//这tm才叫初始化 书上写些锤    子
	student* root;
	string kk;
	cin >> kk;
	creat(root, kk);//

	//接下来是不带头节点的线索化
	clue_tree(root);//正确
	
	//接下来两步骤是遍历同时输出
	display_the_tree(root);


	


	return 0;
}

  • 17
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨骅麟(Patrick Young)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值