贴出学习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> &copy);
}; 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> &copy)
{
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);//重载赋值运算符
}; //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> &copy)
{
if(&copy!=this)
{
DestroyHelp(root);
root=CopyTreeHelp(copy.root);
}
return *this;
}

线索化二叉树的构建与先序,中序遍历(C++版)的更多相关文章

  1. 数据结构与算法---线索化二叉树(Threaded BinaryTree)

    先看一个问题 将数列 {1, 3, 6, 8, 10, 14  } 构建成一颗二叉树 问题分析: 当我们对上面的二叉树进行中序遍历时,数列为 {8, 3, 10, 1, 6, 14 } 但是 6, 8 ...

  2. 后序线索化二叉树(Java版)

    前面介绍了前序线索化二叉树.中序线索化二叉树,本文将介绍后序线索化二叉树.之所以用单独的一篇文章来分析后序线索化二叉树,是因为后序线索化二叉树比前序.中序要复杂一些:另外在复习线索化二叉树的过程中,大 ...

  3. YTU 3026: 中序线索化二叉树

    原文链接:https://www.dreamwings.cn/ytu3026/2896.html 3026: 中序线索化二叉树 时间限制: 1 Sec  内存限制: 128 MB 提交: 9  解决: ...

  4. 图解中序遍历线索化二叉树,中序线索二叉树遍历,C\C++描述

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  5. 图解前序遍历线索化二叉树,前序线索二叉树遍历,C\C++描述

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  6. JAVA递归实现线索化二叉树

    JAVA递归实现线索化二叉树 基础理论 首先,二叉树递归遍历分为先序遍历.中序遍历和后序遍历. 先序遍历为:根节点+左子树+右子树 中序遍历为:左子树+根节点+右子树 后序遍历为:左子树+右子树+根节 ...

  7. C#数据结构-线索化二叉树

    为什么线索化二叉树? 对于二叉树的遍历,我们知道每个节点的前驱与后继,但是这是建立在遍历的基础上,否则我们只知道后续的左右子树.现在我们充分利用二叉树左右子树的空节点,分别指向当前节点的前驱.后继,便 ...

  8. 【IT笔试面试题整理】给定二叉树先序中序,建立二叉树的递归算法

    [试题描述]:  给定二叉树先序中序,建立二叉树的递归算法 其先序序列的第一个元素为根节点,接下来即为其左子树先序遍历序列,紧跟着是右子树先序遍历序列,固根节点已可从先序序列中分离.在中序序列中找到 ...

  9. 二叉树 遍历 先序 中序 后序 深度 广度 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

随机推荐

  1. ajax异步加载遮罩层特效

    <!doctype html> <html> <head> <title>遮罩层(正在加载中)</title> <meta chars ...

  2. [leetcode-604-Design Compressed String Iterator]

    Design and implement a data structure for a compressed string iterator. It should support the follow ...

  3. 【LeetCode】217. Contains Duplicate

    题目: Given an array of integers, find if the array contains any duplicates. Your function should retu ...

  4. MarsEdit快速插入源代码

    开始用MarsEdit来写博文,客户端的,毕竟是要方便的多啊. 遇到的第一个问题就是:MarsEdit没有提供快速插入源代码的工具,而对于我这枚码农而言,这个就有点太杯具了. 简单研究了一下,发现Ma ...

  5. oracle预定义角色

    角色是相关权限的集合,使用角色能够简化权限的管理.简而言之就是oracle可以事先把一系列权限集中在一起(角色),打包赋予给用户,那么用户就具有了角色的一系列权限. oracle预定义角色有25种,它 ...

  6. mysql常见的优化方法

    1.选取适当的字段属性.例如,在定义邮政编码这个字段时,如果将其设置为CHAR(255),显然给数据库增加了不必要的空间,甚至使用VARCHAR这种类型也是多余的,因为CHAR(6)就可以很好的完成任 ...

  7. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'portal.hibernate_sequence' doesn't exist, 谈谈主键自增的方式

    最近几天几天做项目用到了Spring Data JPA,确实是个好东西,省了很多力气.但是由于刚开始用,也遇到不少头疼的问题,如下,调用JpaRepository接口的save方法保存一个对象到数据库 ...

  8. Django学习(四)---Admin配置

    1)Admin: admin是django自带的功能强大的自动化数据管理界面 被授权的用户可以直接在Admin中管理数据库(增.删.改.查) Django提供了许多针对Admin的定制功能 2)配置A ...

  9. UVa455 Periodic String 的wronganswer问题探讨,以及AC的新思路

    题目的意思是一个字符串有某个长度为k的字符串通过不断重复形成的,而k被称为该字符串的周期.而我们所要做的是找出该字符串的最小周期. input The first line is an integer ...

  10. [信息安全] 3.HTTPS工作流程

    [信息安全]系列博客:http://www.cnblogs.com/linianhui/category/985957.html 0. 简单回顾 在前面两篇博客中介绍了密码相关的一些基本工具,包括(对 ...