C++线索二叉树的相关操作
Posted Roam-G
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++线索二叉树的相关操作相关的知识,希望对你有一定的参考价值。
C++线索二叉树的相关操作
#pragma once
//5.21 --212--线索二叉树的类定义
template<class T>
struct ThreadNode
int ltag, rtag;
ThreadNode<T>* leftChild, * righChild;
T data;
ThreadNode(const T item) :data(item), leftChild(nullptr), righChild(nullptr),
ltag(0), rtag(0)
;
template<class T>
class ThreadTree
protected:
ThreadNode<T>* root;
void createInThread(ThreadNode<T>* current, ThreadNode<T>*& pre);
//中序遍历建立二叉树
ThreadNode<T>* parent(ThreadNode<T>* t);
//寻找结点t的父结点
public:
ThreadTree() :root(nullptr)
void createInThread();
ThreadNode<T>* First(ThreadNode<T>* current);//寻找第一个结点
ThreadNode<T>* Last(ThreadNode<T>* current);//寻找最后一个结点
ThreadNode<T>* Next(ThreadNode<T>* current);//寻找 后继结点
ThreadNode<T>* Prior(ThreadNode<T>* current);//寻找 前驱结点
void InOrder(void (*visit)(ThreadNode<T>* p));
void PreOrder(void (*visit)(ThreadNode<T>* p));
void PostOrder(void (*visit)(ThreadNode<T>* p));
void InsertRight(ThreadNode<T>* current);//插入一个结点
//........
;
//5.22 --213-中序二叉树 成员函数实现
//求序列的 第一个结点
template<class T>
ThreadNode<T>* ThreadTree<T>::First(ThreadNode<T>* current)
//以*current為根的 第一个结点
ThreadNode<T>* p = current;
while (p->ltag == 0) //只要有 左子女,就一直向左
p = p->leftChild;//最左下结点,(不一定是叶子结点)
//最左边的就是 中序遍历的第一个结点。
return p;
;
//求后继
template<class T>
ThreadNode<T>* ThreadTree<T>::Next(ThreadNode<T>* current)
ThreadNode<T>* p = current->righChild;
if (current->rtag == 0) //该点 A有 右子女,
return First(p);//求该点的右子女为根的子树的 第一个结点就是E
else//否则就是 rtag==1.存放的就是后继结点。
return p;//返回后继结点
;
//序列的最后一个结点
template<class T>
ThreadNode<T>* ThreadTree<T>::Last(ThreadNode<T>* current)
ThreadNode<T>* p = current;
while (p->rtag == 0) //只要有右子女,就一直向右。
p = p->righChild;
return p;
;
//求 前驱结点。
template<class T>
ThreadNode<T>* ThreadTree<T>::Prior(ThreadNode<T>* current)
ThreadNode<T>* p = current->leftChild;//先记录改点的左子女,
if (current->ltag == 0) //如果 有左 子女,比如A,
return Last(p);//求以 该点 左子女为根的子树(比如B) 的最右一个结点。
else //否则就是rtag==1,存放的就是 前驱结点
return p;
;
//5.23进行中序遍历
template<class T>
void ThreadTree<T>::InOrder(void (*visit)(ThreadNode<T>* p))
ThreadNode<T>* p;
for (p = First(root);p != nullptr;p = Next(p))
visit(p);
;
//5.24利用中序遍历 对二叉树进行中序线索化
template<class T>
void ThreadTree<T>::createInThread()
ThreadNode<T>* pre = nullptr;//前驱结点指针
if (root != nullptr) //非空二叉树,进行线索化
createInThread(root, pre);//中序遍历 线索化
pre->righChild = nullptr;//后 处理中序最后一个结点指针。(最后一个是特殊的)
pre->rtag = 1;
;
template<class T>
void ThreadTree<T>::createInThread(ThreadNode<T>* current,
ThreadNode<T>*& pre)
//通过中序遍历,对二叉树进行线索化
if (current == nullptr)
return;
createInThread(current->leftChild, pre);//递归,左子树线索化
if (current->leftChild == nullptr) //建立当前结点的前驱
current->leftChild = pre;
current->ltag = 1;
if (pre != nullptr && pre->righChild == nullptr)
pre->righChild = current;//建立当前结点的后继
pre->rtag = 1;
pre = current;
createInThread(current->righChild, pre);//递归,右子树线索化
;
//5.25 在中序遍历二叉树上实现前序遍历算法
template<class T>
void ThreadTree<T>::PreOrder(void (*visit)(ThreadNode<T>* current))
ThreadNode<T>* current = root;
while (current != null)
visit(current);//访问根结点
if (current->ltag == 0) //如果有 左子女.即为 后继
current = current->leftChild;
else if (current->rtag == 0) //否则 有 右子女,即为后继
current = current->righChild;
else
//沿着后继继续检测
while (current != nullptr && current->rtag == 1)
current = current->righChild;//直到有 右子女的结点
if (current != nullptr) //右 子女 即为后继
current = current->righChild;
;
//5.26 在中序遍历二叉树上实现后序遍历算法
template<class T>
void ThreadTree<T>::PostOrder(void (*visit)(ThreadNode<T>* current))
ThreadNode<T>* current = root;
//寻找最后一个结点
while (current->ltag == 0 || current->rtag == 0)
if (current->ltag == 0)
current = current->leftChild;
else if (current->rtag == 0)
current = current->righChild;
visit(current);//访问第一个结点
ThreadNode<T>* p;
while ((p = parent(t)) != nullptr)
if (p->righChild == current || p->rtag == 1) //*current是*p的后序后继
current = p;
else//否则,current 移动到 p的右子树
current = p->righChild;
while (current->ltag == 0 || current->rtag == 0)
if (current->ltag == 0)
current = current->leftChild;
else if (current->rtag == 0)
current = current->righChild;
visit(current);
;
//5.27 求父结点
template<class T>
ThreadNode<T>* ThreadTree<T>::parent(ThreadNode<T>* t)
ThreadNode<T>* p;
if (t == root)return nullptr;//根结点 无父结点
for (p = t;p->ltag == 0;p = p->leftChild);//求 t为根子树第一个结点。
if (p->leftChild != nullptr)
for (p = p->leftChild;
p != nullptr && p->leftChild != t && p->righChild != t;
p = p->righChild);
if (p == nullptr || p->leftChild == nullptr)
for (p = t;p->rtag == 0;p = p->righChild);
for (p = p->righChild;p != nullptr && p->leftChild != t && p->righChild != t;
p = p->leftChild);
return p;
;
//5.28
template<class T>
void ThreadTree<T>::InsertRight(ThreadNode<T>* s, ThreadNode<T>* r)
//将新结点*r当做*s的 右子女插入
r->rightChild = s->rightChild;//s的右子女或者后继 线索 传给r
r->rtag = s->rtag;//后继线索 标志一同传送
t->leftChild = s;
r->ltag = 1;
s->rightChild = r;//r成为s右子女
s->rtag = 0;
if (r->rtag == 0) //s原来有右子女
ThreadNode<T>* temp;
temp = First(r->rightChild);//在s原来的柚子树找中序遍历 第一个点
temp->leftChild = r;//建立指向r的前驱线索
;
//在*s的左子女处插入 *p
template<class T>
void ThreadTree<T>::InsertRight(ThreadNode<T>* s, ThreadNode<T>* p)
if (s != nullptr && p != nullptr)
if (s->rtag) //首先判断 是否有子女。 无!
p->leftChild = s->leftChild;//s的左线索 复制给 p
p->rtag = 1; //p无右子女
else //有左子女
p->leftChild = s->leftChild;
p->ltag = 0;//插入
p->rightChild = s;//p的后继 是s
p->rtag = 1;//p无右子女
ThreadNode<T>* temp = p->leftChild;
while (!temp->rtag) //找p左子树 中序遍历中的最后一个点。
temp = temp->rightChild;
temp->rightChild = p;//该点的后继 是 p
s->leftChild = p;
s->ltag = 0;
;
以上是关于C++线索二叉树的相关操作的主要内容,如果未能解决你的问题,请参考以下文章