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++线索二叉树的相关操作的主要内容,如果未能解决你的问题,请参考以下文章

PHP数据结构-完全二叉树线索二叉树及树的顺序存储结构

c++ 二叉树的线索化(前中后序遍历)

PHP数据结构-完全二叉树线索二叉树及树的顺序存储结构

Python数据结构系列☀️《树与二叉树-基础知识》——知识点讲解+代码实现☀️

二叉树的线索

线索二叉树的定义和操作