贴出学习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. js禁止选中(网页复制)

    document.onselectstart=new Function("event.returnValue=false");//禁止选中(无法复制) document.oncon ...

  2. ReactJS基础(续)

    前边的ReactJS基础,我们可以了解到,对于React,可以说是万物皆组件 React的组件应该具有 可组合(Composeable)可重用(Reusable)可维护(Maintainable)的特 ...

  3. H5在线编辑器优化总结

    花了三个半月做了个编辑器.自己一个人写写CSS,搞搞html,弄下JS,大部分精力都是掏鼓js,时间很仓促,后面领导帮忙写了四个页面逻辑(音频,图片,视频). 很多能优化的,以此文章记录要已经优化和未 ...

  4. Oracle数据库中的重要对象

    数据库中的重要对象:表.视图.序列.函数.存储过程.索引.同义词1.表:用PL/SQL Developer 软件打开 Scott的DEPT表查看SQL,可以看见DEPT表创建的脚本-- Create ...

  5. NavigationView的头部的事件监听

    现在App的UI设计中Drawerlayout+NavigationView是一个比较常用的设计了,而以前我一般只是在Navigation中的menu(即下部的item中)添加事件监听,而今天碰到一个 ...

  6. 从一个针对ASP.NET MVC框架的Controller.Action的请求处理顺序来说整个请求过程。

    下面引用的所有代码都来自ASP.NET MVC的源码,但是可能只选取每个方法的其中一部分. System.Web.Routing.UrlRoutingModule在管道事件中注册PostResolve ...

  7. 关于IO流代码BufferedReader

    package JBJADV003;import java.io.*;public class BufferedReaderTest { /** * @param args */ public sta ...

  8. 关于STM32单片机的IAP实现

    基于STM32F103单片机的IAP实现(虽然该篇文章不会详细写出实现细节,但是会从一个全局的角度讲述,实际的实现细节只需根据datasheet即可完成). 一.基础概念 什么是IAP?IAP即在应用 ...

  9. English - 被动语态的翻译原则

    被动语态翻译原则 1. Passive ----> Active The bag is stolen by him. One the whole, such a conclusion can b ...

  10. ubuntu(linux)新装系统恢复备份后无法进入系统问题的解决

    1. 引子: 可以跳过直接看3.~5. 我们可能会遇到这样的状况,从ubuntu转到别的系统,兜兜转转又回到了ubuntu. 比如说: Fedora升级后一大堆BUG,与java有关的软件渲染都糟糕的 ...