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

原创 2015年11月20日 13:00:08

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

#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;
}


相关文章推荐

二叉树系列(1)已知二叉树的中序遍历和前序遍历,如何求后序遍历

(昨晚HULU的笔试题之一,被鄙视的惨,面对向往已久的公司,交出苍白无力的答卷,心里像被剜了一刀。再多解释都是苍白。我鄙视我自己。现在开始舔舐伤口。) 假设有棵树,长下面这个样子,它的前序遍历,中...

给出先序序列,中序序列恢复二叉树

//给出先序序列,中序序列恢复出二叉树的方法 //方法1:利用递归的方法,首先先找出根节点,然后有先序和后序的特点可知:先序序列中在根节点左边的是左子树,根节点右面的是右子树 //有此来,进行递归...

【数据结构基础】前序、中序、后序线索化二叉树(非递归实现)

前言: 花了整整一天时间写完了二叉树的线索化的递归实现和非递归实现。目的有两个: 一是 熟悉树的递归和非递归遍历。 二是 琢磨琢磨递归方法。 在写的过程中发现网上很少有线索二叉...

笔记九:二叉树的创建、递归与非递归版前序、中序、后序查找、树高和节点判断

代码:#include #include #include using namespace std; template struct binaryTreeNode{ T element; ...

二叉排序树的创建,删除结点;树的前序,中序,后序非递归遍;二叉树的线索化

#include #include using namespace std; typedef int ELEMENT_TYPE; //定义树的结点 typedef struct Node{ ELEM...

数据结构--树--线索二叉树(中序,前序,后序)

线索二叉树 在遍历二叉树的时候,会有许多空指针域,这些空间不存储任何事物,白白浪费了内存的资源。 那么在做遍历的时候,提前记录下每个结点的前驱和后继,这样就更加节约了时间。              ...

中序线索化二叉树及中序遍历

  • 2008年04月01日 21:43
  • 2KB
  • 下载

数据结构(十五) 线索二叉树讲解(带头节点中序加线索) 以及实现的完整代码

这篇博客主要讲解的是中序线索化的基础上加上头节点(前序类似),这样做的好处是可以让所有的指针都不为空(即都有指向)。 下篇博客主要讲解后序加上线索化,这个有一定的难度。 实现的代码如下:...

Construct Binary Tree from Inorder and Postorder Traversal(给出中序后序求二叉树)

Given inorder and postorder traversal of a tree, construct the binary tree. Note: You may assume th...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:给出二叉树,将二叉树进行中序线索化,在根据中序线索化二叉树,找出给定节点的前序后继节点,和给出节点的后序后继节点
举报原因:
原因补充:

(最多只允许输入30个字)