线索化二叉树的构建与先序,中序遍历(C++版)
贴出学习C++数据结构线索化二叉树的过程,
方便和我一样的新手进行测试和学习
同时欢迎各位大神纠正。
不同与普通二叉树的地方会用背景色填充
//BinTreeNode_Thr.h
enum PointTag
{Link,Thread}; template<typename ElemType>
struct BinTreeNode
{
ElemType data; //数据元素
PointTag LTag,RTag; //左标志,右标志
BinTreeNode<ElemType> *leftChild; //指向左孩子的指针
BinTreeNode<ElemType> *rightChild; //指向右孩子的指针
//函数构造
BinTreeNode();
BinTreeNode(const ElemType &val,
BinTreeNode<ElemType> *lChild=NULL,
BinTreeNode<ElemType> *rChild=NULL);
BinTreeNode<ElemType> &operator =(const BinTreeNode<ElemType> ©);
}; template<typename ElemType>
BinTreeNode<ElemType>::BinTreeNode()
{
leftChild=rightChild=NULL;
LTag=RTag=Link; //此处初始化为Link,即存在孩子
} template<typename ElemType>
BinTreeNode<ElemType>::BinTreeNode(const ElemType &val,
BinTreeNode<ElemType> *lChild,
BinTreeNode<ElemType> *rChild)
{
data=val;
LTag=RTag=Link; //初始化为Link
leftChild=lChild;
rightChild=rChild;
} template<typename ElemType>
BinTreeNode<ElemType> &BinTreeNode<ElemType>::operator =(const BinTreeNode<ElemType> ©)
{
data=copy.data;
leftChild=copy.leftChild;
rightChild=copy.leftChild;
LTag=copy.LTag;
RTag=copy.RTag;
}
//BinaryTree_Thr.h
#include"BinTreeNode_Thr.h"
template<typename ElemType>
class BinaryTree_Thr
{
protected:
//数据成员
BinTreeNode<ElemType> *root;
//辅助函数
BinTreeNode<ElemType> *CopyTreeHelp(const BinTreeNode<ElemType> *r);//复制二叉树
void DestroyHelp(BinTreeNode<ElemType> *&r);//销毁r为根的二叉树
void PreThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre); //先序线索化
void InThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre); //中序线索化
void CreateBTreeHelp(BinTreeNode<ElemType> *&r,ElemType pre[],ElemType in[],int,int,int,int);//用中序和先序序列构造树
public:
BinaryTree_Thr(){root=NULL}//无参构造
BinaryTree_Thr(BinTreeNode<ElemType> *r){ root=r;}//建立以r为根的二叉树
virtual ~BinaryTree_Thr();//有指针自定义虚构,且用虚虚构
BinaryTree_Thr<ElemType> &CreateBTree(ElemType pre[],ElemType in[],int n); //构造树
void PreTreading();//先序线索化
void InTreading();//中序线索化
void PreOrderTraverse_Thr(void (*visit) (const ElemType &))const; //先序遍历
void InOrderTraverse_Thr(void (*visit) (const ElemType &))const; //中序遍历
void LevelOrder(void (*visit) (const ElemType &))const;
BinaryTree_Thr<ElemType> &operator =(const BinaryTree_Thr<ElemType> ©);//重载赋值运算符
}; //Copy
template<typename ElemType>
BinTreeNode<ElemType> *BinaryTree_Thr<ElemType>::CopyTreeHelp(const BinTreeNode<ElemType> *r)
{
BinTreeNode<ElemType> *cur;
if(r==NULL) cur=NULL;
else
{
BinTreeNode<ElemType> *lChild=CopyTreeHelp(r->leftChild);//复制左子树
BinTreeNode<ElemType> *rChild=CopyTreeHelp(r->rightChild);//复制右子树
cur=new BinTreeNode<ElemType>(r->data,lChild,rChild);
//复制根节点
}
return cur;
} template<typename ElemType>
void BinaryTree_Thr<ElemType>::InThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre)//中序遍历
{
if(p)
{
if(p->LTag==Link)
InThreadingHelp(p->leftChild,pre); //线索化左子树.
if(!p->leftChild) //左孩子空
{
p->LTag=Thread;
p->leftChild=pre;
}
if(!pre->rightChild) //前驱 的右孩子空
{
pre->RTag=Thread;
pre->rightChild=p;
}
pre=p;
if(p->RTag==Link)
InThreadingHelp(p->rightChild,pre); //线索化右子树
} } template<typename ElemType>
void BinaryTree_Thr<ElemType>::PreThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre)//先序遍历
{
if(p)
{
if(!p->leftChild) //左孩子空
{
p->LTag=Thread;
p->leftChild=pre;
}
if(!pre->rightChild) //前驱 的右孩子空
{
pre->RTag=Thread;
pre->rightChild=p;
}
pre=p;
if(p->LTag==Link)
PreThreadingHelp(p->leftChild,pre); //线索化左子树.
if(p->RTag==Link)
PreThreadingHelp(p->rightChild,pre); //线索化右子树
} } template<typename ElemType>
void BinaryTree_Thr<ElemType>::DestroyHelp(BinTreeNode<ElemType> *&r)
{
if(r!=NULL)
{
if(r->LTag==Link)
DestroyHelp(r->leftChild);
if(r->RTag==Link)
DestroyHelp(r->rightChild);
delete r;
r=NULL;
}
} //虚构
template<typename ElemType>
BinaryTree_Thr<ElemType>::~BinaryTree_Thr()
{
DestroyHelp(root);
} template<typename ElemType>
//Thr为头节点,T为根.
void BinaryTree_Thr<ElemType>::InTreading()
{
BinTreeNode<ElemType> *pre=root;
InThreadingHelp(root,pre); //中序线索化
if(pre->rightChild==NULL)
pre->RTag=Thread; //处理最后一个节点
} template<typename ElemType>
void BinaryTree_Thr<ElemType>::PreTreading()
{
BinTreeNode<ElemType> *pre=root;
PreThreadingHelp(root,pre); //先序线索化
if(pre->rightChild==NULL)
pre->RTag=Thread; //处理最后一个节点
} template<typename ElemType>
void print(const ElemType &e )
{
cout<<e<<" ";
} template<typename ElemType>
void BinaryTree_Thr<ElemType>::InOrderTraverse_Thr(void (*visit) (const ElemType &))const
{
visit=print;
if(root!=NULL){
BinTreeNode<ElemType> *p=root; //p指向根
while(p->LTag==Link) p=p->leftChild; //左走至最左下角
while(p)
{
(*visit)(p->data); //访问结点元素
if(p->RTag==Thread) //右孩子为线索,则p指向后继
{
p=p->rightChild;
}
else //右孩子存在
{
p=p->rightChild; //遍历右孩子
while(p->LTag==Link)
p=p->leftChild;
}
}
}
} template<typename ElemType>
void BinaryTree_Thr<ElemType>::PreOrderTraverse_Thr(void (*visit) (const ElemType &))const
{
visit=print;
if(root!=NULL){
BinTreeNode<ElemType> *p=root; //p指向根
while(p)
{
(*visit)(p->data);
if(p->RTag==Thread)
p=p->rightChild;
else
{
if(p->LTag==Link)
p=p->leftChild;
else
p=p->rightChild;
}
}
}
} template<typename ElemType>
void BinaryTree_Thr<ElemType>::CreateBTreeHelp(BinTreeNode<ElemType> *&r,
ElemType pre[],ElemType in[],
int preLeft,int preRight,int inLeft,int inRight) {
if(preLeft>preRight||inLeft>inRight)
r=NULL;
else
{
r=new BinTreeNode<ElemType>(pre[preLeft]);//生成根结点
int mid=inLeft;
while(in[mid]!=pre[preLeft])
mid++;
CreateBTreeHelp(r->leftChild,pre,in,preLeft+,preLeft+mid-inLeft,inLeft,mid-); //这里如果不懂建议自己画图手工实现一遍。
CreateBTreeHelp(r->rightChild,pre,in,preLeft+mid-inLeft+,preRight,mid+,inRight);
}
} template<typename ElemType>
//构造树
BinaryTree_Thr<ElemType>& BinaryTree_Thr<ElemType>::CreateBTree(ElemType pre[],ElemType in[],int n)
{
BinTreeNode<ElemType> *r; //根
CreateBTreeHelp(r,pre,in,,n-,,n-);
//return BinaryTree<ElemType>(r);//,不能这么返回,Error:不应该返回局部变量的地址
*this = BinaryTree_Thr<ElemType>(r);
return *this;
} #include<queue>
template<typename ElemType>
void BinaryTree_Thr<ElemType>::LevelOrder(void (*visit) (const ElemType &))const
{ //队列实现
visit=print;
queue<BinTreeNode<ElemType> *> q;
BinTreeNode<ElemType> *t=root;
if(t!=NULL) q.push(t); //根非空,入队
while(!q.empty()) //队不空
{
t=q.front();
q.pop(); //出队
(*visit)(t->data); //一层一层进行遍历,无法理解还是自己画图实现一遍
if(t->leftChild)
q.push(t->leftChild); //遍历左孩子
if(t->rightChild)
q.push(t->rightChild); //遍历右孩子
} } //operator =
template<typename ElemType>
BinaryTree_Thr<ElemType> &BinaryTree_Thr<ElemType>::operator=(const BinaryTree_Thr<ElemType> ©)
{
if(©!=this)
{
DestroyHelp(root);
root=CopyTreeHelp(copy.root);
}
return *this;
}
线索化二叉树的构建与先序,中序遍历(C++版)的更多相关文章
- 数据结构与算法---线索化二叉树(Threaded BinaryTree)
先看一个问题 将数列 {1, 3, 6, 8, 10, 14 } 构建成一颗二叉树 问题分析: 当我们对上面的二叉树进行中序遍历时,数列为 {8, 3, 10, 1, 6, 14 } 但是 6, 8 ...
- 后序线索化二叉树(Java版)
前面介绍了前序线索化二叉树.中序线索化二叉树,本文将介绍后序线索化二叉树.之所以用单独的一篇文章来分析后序线索化二叉树,是因为后序线索化二叉树比前序.中序要复杂一些:另外在复习线索化二叉树的过程中,大 ...
- YTU 3026: 中序线索化二叉树
原文链接:https://www.dreamwings.cn/ytu3026/2896.html 3026: 中序线索化二叉树 时间限制: 1 Sec 内存限制: 128 MB 提交: 9 解决: ...
- 图解中序遍历线索化二叉树,中序线索二叉树遍历,C\C++描述
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- 图解前序遍历线索化二叉树,前序线索二叉树遍历,C\C++描述
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- JAVA递归实现线索化二叉树
JAVA递归实现线索化二叉树 基础理论 首先,二叉树递归遍历分为先序遍历.中序遍历和后序遍历. 先序遍历为:根节点+左子树+右子树 中序遍历为:左子树+根节点+右子树 后序遍历为:左子树+右子树+根节 ...
- C#数据结构-线索化二叉树
为什么线索化二叉树? 对于二叉树的遍历,我们知道每个节点的前驱与后继,但是这是建立在遍历的基础上,否则我们只知道后续的左右子树.现在我们充分利用二叉树左右子树的空节点,分别指向当前节点的前驱.后继,便 ...
- 【IT笔试面试题整理】给定二叉树先序中序,建立二叉树的递归算法
[试题描述]: 给定二叉树先序中序,建立二叉树的递归算法 其先序序列的第一个元素为根节点,接下来即为其左子树先序遍历序列,紧跟着是右子树先序遍历序列,固根节点已可从先序序列中分离.在中序序列中找到 ...
- 二叉树 遍历 先序 中序 后序 深度 广度 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
随机推荐
- curl通过调用WebService查询当前天气
<?php /** * curl通过调用WebService查询北京的当前天气 */ header("Content-type: text/html; charset=utf-8&qu ...
- 国内互联网公司github网址
-----------------------------------------------------推荐技术------------------------------------------- ...
- axis1.4开发webservice客户端(快速入门)-基于jdk1.4
写在前面: 对于客户端,服务端开发好了以后,客户端只需要调用就可以了.这里我们讲的是,根据服务的访问地址,来生成客户端所需要用到的代码(听说有几种调用方式,但是用到最常见的就是stub方式,貌似我说的 ...
- React Image加载图片过大导致ListView滑动卡顿
今天莫名的发现ListView加载Item很卡,一顿一顿的... ListView Item 中只加载一张图片,小编从百度爸爸上随便复制的链接,这张图片很大,以致埋下如此大坑... Image的Sty ...
- Java学习笔记之集合
集合(Collection)(掌握) (1)集合的由来? 我们学习的是Java -- 面向对象 -- 操作很多对象 -- 存储 -- 容器(数组和StringBuffer) -- 数组而数组的长度固定 ...
- Python 操作 MYSQL
本文介绍了 Python 操作 MYSQL.执行 SQL 语句.获取结果集.遍历结果集.取得某个字 段.获取表字段名.将图片插入数据库.执行事务等各种代码实例和详细介绍,代码居多, 是一桌丰盛唯美的代 ...
- Python数据分析之路(一)查询和统计
0. 如何入门数据分析 关注沙漠之鹰的同学一定看过沙漠君写得很多篇数据分析文章,比如分析房价,车价,预测机动车摇号这些话题.其实文章中所有的分析都使用了Python和它非常强大的数据分析库Pandas ...
- Spring3 MVC 类型转换
1. Spring在进行类型转化都是基于java.beans.PropertyEditor接口. 2. 可以使用@InitBinder来进行对单个controller的类型进行操作,比如添加Date类 ...
- Bash : 索引数组
Bash 提供了两种类型的数组,分别是索引数组(indexed array)和关联数组(associative array).本文主要介绍索引数组的基本用法. 索引数组的基本特点 Bash 提供的数组 ...
- 树状数组(瞎bb) [树状数组]
Copyright:http://www.cnblogs.com/ZYBGMZL/ 树状数组是一个利用一维数组和位运算组成的求解区间问题的高效数据结构,其构造如图所示 首先,我们要用它解决单点修改.区 ...