给出二叉树,将二叉树进行中序线索化,在根据中序线索化二叉树,找出给定节点的前序后继节点,和给出节点的后序后继节点

这篇博客介绍了如何对二叉树进行中序线索化,并详细阐述了在线索化二叉树中查找给定节点的前序和后序后继节点的算法过程,附带相关代码实现和注释。
摘要由CSDN通过智能技术生成

该程序,最部分功能进行了详细的说明,在给别程序块中给出了详细的算法和注释

#ifndef BINARYTREENODE_H
#define BINARYTREENODE_H
template<typename T>
class BinaryTreeNode{
public:
	T data;
	int leftTag;
	int rightTag;
	BinaryTreeNode<T>* leftChild;
	BinaryTreeNode<T>* rightChild;
	BinaryTreeNode<T>* parent;
	BinaryTreeNode(){

	}
	BinaryTreeNode(const T& val, int leftTag, int rightTag, BinaryTreeNode<T>* str, BinaryTreeNode<T>* ptr,BinaryTreeNode<T>* p) :data(val), leftTag(leftTag), rightTag(rightTag), leftChild(str), rightChild(ptr),parent(p){

	}
};
#endif
#ifndef THREADBINARYTREE_H
#define THREADBINARYTREE_H
#include"BinaryTreeNode.h"
#include<iostream>
#include<queue>
using namespace std;
template<typename T>
class ThreadBinaryTree{
private:
	BinaryTreeNode<T>* root;
	BinaryTreeNode<T>* pre;
private:
	void Clear(BinaryTreeNode<T>* &str);
	void Creat();
	void AddLeaf(BinaryTreeNode<T>* &str);
	void PrintIorder()const;
	void ThreadTree()const;
	void ThreadIonderTree(BinaryTreeNode<T>* str,BinaryTreeNode<T>* ptr);
	void PrintVal(BinaryTreeNode<T>* str)const;
	BinaryTreeNode<T>* Find(const T& val)const;
	//在中序序列下,找到给定节点的前序后继节点
	BinaryTreeNode<T>* InorderSuccessor(BinaryTreeNode<T>* str);
	//在中序线索二叉树中找出给定节点的后序后继
	BinaryTreeNode<T>* PostIonderSuccessor(BinaryTreeNode<T>* str);
public:
	ThreadBinaryTree();
	~ThreadBinaryTree();
	void simulate();
};
template<typename T>
ThreadBinaryTree<T>::ThreadBinaryTree()
{
	this->root = NULL;
	this->pre = NULL;
}
template<typename T>
ThreadBinaryTree<T>::~ThreadBinaryTree()
{
	this->Clear(this->root);
}
template<typename T>
void ThreadBinaryTree<T>::Clear(BinaryTreeNode<T>* &str)
{
	queue<BinaryTreeNode<T>*>node;
	if (str == NULL)
		return;
	node.push(str);
	while (!node.empty())
	{
		str = node.front();
		node.pop();
		if (str->leftChild&&str->leftTag == 0)
			node.push(str->leftChild);
		if (str->rightChild&&str->rightTag == 0)
			node.push(str->rightChild);
		delete str;
	}
	str = NULL;
}
template<typename T>
void ThreadBinaryTree<T>::Creat()
{
	this->AddLeaf(this->root);
}
template<typename T>
void ThreadBinaryTree<T>::AddLeaf(BinaryTreeNode<T>* &str)
{
	T val;
	if (this->root == NULL)
	{
		cout << "input the root :";
	}
	cin >> val;
	if (val == '#')
	{
		str = NULL;
		return;
	}
	str = new BinaryTreeNode<T>(val, 0, 0, NULL, NULL, NULL);
	cout << "input the " << str->data << " leftChild :";
	AddLeaf(str->leftChild);
	cout << "input the " << str->data << " rigthChild :";
	AddLeaf(str->rightChild);
}
template<typename T>
void ThreadBinaryTree<T>::PrintIorder()const
{
	if (this->root == NULL)
	{
		cout << "the tree is empty" << endl;
		return;
	}
	BinaryTreeNode<T>* str = this->root;
	queue<BinaryTreeNode<T>*>node;
	node.push(str);
	while (!node.empty())
	{
		str = node.front();
		node.pop();
		if (str->leftChild)
		{
			node.push(str->leftChild);
			str->leftChild->parent = str;
		}
		if (str->rightChild)
		{
			node.push(str->rightChild);
			str->rightChild->parent = str;
		}
		cout << str->data << " ";
	}
}
template<typename T>
void ThreadBinaryTree<T>::simulate()
{
	this->Creat();
	this->PrintIorder();
	cout << endl;
	cout << "输入你要查找的元素:";
	T val;
	cin >> val;
	BinaryTreeNode<T>* str = this->Find(val);
	this->ThreadIonderTree(this->root, this->pre);
	cout << "输出" << val << "的前序后继";
	this->PrintVal(this->InorderSuccessor(str));
	cout << endl;
	cout << "输出" << val << "的后序后继";
	this->PrintVal(this->PostIonderSuccessor(str));
}
template<typename T>
void ThreadBinaryTree<T>::ThreadIonderTree(BinaryTreeNode<T>* str,BinaryTreeNode<T>* ptr)
{
	BinaryTreeNode<T>* current = str;
	if (current != NULL)
	{
		//在中徐线索化的过程中,值需要考虑到两种情况
		//首先明确中序线索化的过程   左->中->右,这就是中序线索化的过程
		//所以中序遍历过程中的第一个节点应该是左子树中的“最左的节点”
		//所以情况为两种
		//1:如果该节点的左子树为空,则执行current->leftChild=pre;current->leftTag=1;
		//2:如果pre节点存在,且pre节点的右子树不存在,则说明该节点应该是左子树中的“最右子树”或者是右子树中的“最右子树”
		//执行一下过程,pre->rightChild=root;pre->rightTag=1;
		ThreadIonderTree(current->leftChild, pre);
		if (current->leftChild == NULL)
		{
			current->leftChild = pre;
			current->leftTag = 1;
		}
		if ((pre) && pre->rightChild == NULL)
		{
			pre->rightChild = this->root;
			pre->rightTag = 1;
		}
		pre = current;
		ThreadIonderTree(current->rightChild, pre);
	}
}
template<typename T>
void ThreadBinaryTree<T>::PrintVal(BinaryTreeNode<T>* str)const
{
	if (str == NULL)
	{
		cout << "该节点没有前序后继结点" << endl;
		return;
	}
	cout << str->data << endl;
}
template<typename T>
BinaryTreeNode<T>* ThreadBinaryTree<T>::Find(const T& val)const
{
	BinaryTreeNode<T>* str = this->root;
	if (str == NULL)
	{
		cout << "the tre is empty" << endl;
		exit(true);
	}
	queue<BinaryTreeNode<T>*>node;
	node.push(str);
	while (!node.empty())
	{
		str = node.front();
		node.pop();
		if (str->leftChild)
			node.push(str->leftChild);
		if (str->rightChild)
			node.push(str->rightChild);
		if (str->data == val)
		{
			break;
		}
	}
	return str;
}
template<typename T>
BinaryTreeNode<T>* ThreadBinaryTree<T>::InorderSuccessor(BinaryTreeNode<T>* str)
{
	//方法分析:首先要注意前序遍历的规则,在注意规则的同时,要注意给出节点的标记位
	//1:如果当前节点的左孩子存在,则该节点的左孩子即为要查找的节点
	//2:如果给出节点的左孩子为空即leftTag=1,而且右孩子存在,则该节点的右孩子为要被查找的节点
	//3:如果给出节点的左右孩子均为空,则需要找出该节点的父节点
	//开始分析要找出父节点的情况
	//1:如果该节点是父节点的左孩子节点,而且该父节点的右孩子存在,则该节点的后继节点为兄弟节点
	//2: 应为该情况是在,给出节点没有左右孩子的情况下给出的,所以不需要在讨论为右孩子的情况
	///该情况下的情况是根节点的左子树已被完全访问,做以需要转到根节点的右子树中
	//找出根节点的右子树中第一个被访问的节点,则该节点则为要查找的节点
	if (str->leftTag == 0)
	{
		return str->leftChild;
	}
	if (str->leftTag == 1 && str->rightTag == 0)
	{
		return str->rightChild;
	}
	//以下代码是给出节点的左右孩子都不存在
	if (str->leftTag == 1 && str->rightTag == 1)
	{
		BinaryTreeNode<T>* ptr = str->parent;
		if (str == ptr->leftChild&&ptr->rightTag == 0)
		{
			return ptr->rightChild;
		}
		if (str == ptr->leftChild&&str->rightTag == 1)
		{
			bool flag = true;
			//q节点将是整个循环跳转到了根节点的右子树中,找出该右子树中第一个被访问的节点
			BinaryTreeNode<T>* q = ptr->rightChild;
			while (q != NULL)
			{
				if (q->rightTag == 0)
				{
					flag = false;
					break;
				}
			}
			if (flag == false)

			{
				return q;
			}
			else
			{
				cout << "error" << endl;
				exit(true);
			}
		}
	}
	return NULL;
}
template<typename T>
BinaryTreeNode<T>* ThreadBinaryTree<T>::PostIonderSuccessor(BinaryTreeNode<T>* str)
{
	//方法分析:
	//首先找出给定节点的父节点,开始判断
	//如果该节点是父节点的右孩子,则说明该节点在后序序列中的后序后继为父节点,即返回父节点即可
	//如果该节点不是父节点的右孩子,则按照后序遍历的规则需要找出父节点的右子树中的“最左子树”
	//即找出,在后序遍历中该节点后的第一个被访问的节点为被查找节点的后序序列中的后继,在这里要特别注意
	//该二叉树已经被线索化,所以在寻找节点是一定要注意关于标记为的状态
	BinaryTreeNode<T>* ptr = str->parent;
	if (ptr->rightChild != str)
	{
		ptr = ptr->rightChild;
		while (ptr->leftChild&&ptr->leftTag == 0)
		{
			ptr = ptr->leftChild;
		}
		return ptr;
	}
	else
		return ptr;
}
#endif
#include"ThreadBinaryTree.h"
int main(int argc, char argv[])
{
	ThreadBinaryTree<char>tree;
	tree.simulate();
	return 0;
}


评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值