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

#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
#include"BinaryTreeNode.h"
#include<iostream>
#include<queue>
using namespace std;
template<typename T>
private:
BinaryTreeNode<T>* root;
BinaryTreeNode<T>* pre;
private:
void Clear(BinaryTreeNode<T>* &str);
void Creat();
void PrintIorder()const;
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:
void simulate();
};
template<typename T>
{
this->root = NULL;
this->pre = NULL;
}
template<typename T>
{
this->Clear(this->root);
}
template<typename T>
{
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>
{
}
template<typename T>
{
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 :";
cout << "input the " << str->data << " rigthChild :";
}
template<typename T>
{
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>
{
this->Creat();
this->PrintIorder();
cout << endl;
cout << "输入你要查找的元素：";
T val;
cin >> val;
BinaryTreeNode<T>* str = this->Find(val);
cout << "输出" << val << "的前序后继";
this->PrintVal(this->InorderSuccessor(str));
cout << endl;
cout << "输出" << val << "的后序后继";
this->PrintVal(this->PostIonderSuccessor(str));
}
template<typename T>
{
BinaryTreeNode<T>* current = str;
if (current != NULL)
{
//在中徐线索化的过程中，值需要考虑到两种情况
//首先明确中序线索化的过程   左->中->右，这就是中序线索化的过程
//所以中序遍历过程中的第一个节点应该是左子树中的“最左的节点”
//所以情况为两种
//1：如果该节点的左子树为空，则执行current->leftChild=pre;current->leftTag=1;
//2：如果pre节点存在，且pre节点的右子树不存在，则说明该节点应该是左子树中的“最右子树”或者是右子树中的“最右子树”
//执行一下过程，pre->rightChild=root;pre->rightTag=1;
if (current->leftChild == NULL)
{
current->leftChild = pre;
current->leftTag = 1;
}
if ((pre) && pre->rightChild == NULL)
{
pre->rightChild = this->root;
pre->rightTag = 1;
}
pre = current;
}
}
template<typename T>
{
if (str == NULL)
{
cout << "该节点没有前序后继结点" << endl;
return;
}
cout << str->data << endl;
}
template<typename T>
{
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>
{
//方法分析：首先要注意前序遍历的规则，在注意规则的同时，要注意给出节点的标记位
//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>* 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
}