上一篇博客对于 二叉树线索化以及线索化的先序、中序、后序遍历做了比较详细的描述
写在前面
其实,我还是很想把本篇博客和二叉树的线索化写在一块的,但是考虑到可能这博客的内容就看足以超过了上一篇的篇幅,考虑到读者可能会疲乏,而且这篇也是线索二叉树中最难的了(查阅了很多网上的资料也鲜有人来讲述后序线索二叉树的遍历,有的就算有也只是把代码放在那里,理解 对于初学者还是有点困难的)
构建节点(多了双亲节点节点)
typedef enum
{
Link,
Thread
}Pointer;
typedef struct TriTreeNode
{
TriTreeNode(const char data)
:_data(data)
, pLeft(NULL)
, pRight(NULL)
, pParent(NULL)
, Ltag(Link)
, Rtag(Link)
{}
char _data;
struct TriTreeNode* pLeft;
struct TriTreeNode* pRight;
struct TriTreeNode* pParent;//双亲
Pointer Ltag, Rtag;
}TriTreeNode;
还是先给出一个树结构吧:
后序线索化二叉树
后序的顺序是:左- 右-根
思路:和先序、中序线索化二叉树的顺序是一样的,在此不再赘述,想看的话上一篇博客会让你满意的。
上代码:
void _PostThreading(TriTreeNode*& Root)
{
if (Root)
{
_PostThreading(Root->pLeft);
_PostThreading(Root->pRight);
if (Root->pLeft == NULL)
{
Root->pLeft = Prev;
Root->Ltag = Thread;
}
if (Prev && Prev->pRight == NULL ) //条件 Prev
{
Prev->pRight = Root;
Prev->Rtag = Thread;
}
Prev = Root;
}
}
如下图,后序线索化的二叉树
!!!
后序遍历线索二叉树
由后序遍历的顺序,我们很容易就想到了找到后序遍历的起点(左子树最左边的节点),然后一直遍历节点的后继(记住每次遍历的前一个节点),当遍历到节点没有后继了,我们就判断是不是到了根节点了(如果根节点没有右子树,就是这种情况了),要是还没有到根节点,那就继续找寻节点的双亲节点(此时就需要我们催节点的结构进行增加双亲节点了),一直找到根节点的位置,继续判断根节点是不是存在右子树(注意这里不能用NULL判断右子树是不是存在,而是用右子树存在的标识Rtag )
好了,描述再多还是代码代码来的实在!!!
void _PostOrder(TriTreeNode* Root)
{
if (Root)
{
TriTreeNode* pCur = Root;
Prev = NULL;
while (pCur != NULL)
{
//第一步:找树最左边的节点
while ( pCur->pLeft != Prev && pCur->Ltag == Link) //左子树
{
pCur = pCur->pLeft;
}
//循环结束后 pCur== Root 或者为空
//第二步:访问后继
while (pCur && pCur->Rtag== Thread)
{
cout << pCur->_data << ' ';
Prev = pCur;
pCur = pCur->pRight;
}
//判断此时pCur是不是指向了根节点
if (pCur == Root)
{
cout << pCur->_data << ' ';
return;
}
while (pCur && pCur->pRight == Prev)
{
cout << pCur->_data << ' ';
Prev = pCur;
pCur = pCur->pParent; //往上一级走
}
//这里不能用NULL判断,而是用Rtag
if (pCur && pCur->Rtag == Link)
{
pCur = pCur->pRight;
}
}
//end-while
}
}
下面就是对代码的一一讲述 <
福利来了>
首先对,大循环中的第一个循环解释(找到最左边的节点)
第二个循环(访问后继)
第三个循环以及后面的判断
后面就是对代码的测试了
来个简单的Tree
加深一点
再难点吧。哈哈
能看到这里的都是好样的!
全部代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
typedef enum
{
Link,
Thread
}Pointer;
typedef struct TriTreeNode
{
TriTreeNode(const char data)
:_data(data)
, pLeft(NULL)
, pRight(NULL)
, pParent(NULL)
, Ltag(Link)
, Rtag(Link)
{}
char _data;
struct TriTreeNode* pLeft;
struct TriTreeNode* pRight;
struct TriTreeNode* pParent;//双亲
Pointer Ltag, Rtag;
}TriTreeNode;
class PostThread_BiTree
{
public://先序遍历创建树
PostThread_BiTree(const char arr[], size_t size)
{
size_t index = 0;
TriTreeNode* parent = NULL;
_Creat_Bitree(_pRoot, arr, size, index, parent);
}
protected:
void _Creat_Bitree(TriTreeNode*& Root, const char arr[], size_t size, size_t& index , TriTreeNode*& parent)
{
if (arr && size > index && arr[index] != '#')
{
Root = new TriTreeNode(arr[index]);
Root->pParent = parent;
_Creat_Bitree(Root->pLeft, arr, size, ++index , Root); //每次传双亲节点
_Creat_Bitree(Root->pRight, arr, size, ++index , Root);
}
}
public:
//后序线索化
void PostTreading()
{
_PostThreading(this->_pRoot);
}
protected:
void _PostThreading(TriTreeNode*& Root)
{
if (Root)
{
_PostThreading(Root->pLeft);
_PostThreading(Root->pRight);
if (Root->pLeft == NULL)
{
Root->pLeft = Prev;
Root->Ltag = Thread;
}
if (Prev && Prev->pRight == NULL ) //条件 Prev
{
Prev->pRight = Root;
Prev->Rtag = Thread;
}
Prev = Root;
}
}
public:
void PostOrder()
{
_PostOrder(this->_pRoot);
}
protected:
void _PostOrder(TriTreeNode* Root)
{
if (Root)
{
TriTreeNode* pCur = Root;
Prev = NULL;
while (pCur != NULL)
{
//第一步:找树最左边的节点
while ( pCur->pLeft != Prev && pCur->Ltag == Link) //左子树
{
pCur = pCur->pLeft;
}
//循环结束后 pCur== Root 或者为空
//第二步:访问后继
while (pCur && pCur->Rtag== Thread)
{
cout << pCur->_data << ' ';
Prev = pCur;
pCur = pCur->pRight;
}
//判断此时pCur是不是指向了根节点
if (pCur == Root)
{
cout << pCur->_data << ' ';
return;
}
while (pCur && pCur->pRight == Prev)
{
cout << pCur->_data << ' ';
Prev = pCur;
pCur = pCur->pParent; //往上一级走
}
//这里不能用NULL判断,而是用Rtag
if (pCur && pCur->Rtag == Link)
{
pCur = pCur->pRight;
}
}
//end-while
}
}
private:
TriTreeNode* _pRoot;
TriTreeNode* Prev;
};
void Test()
{
char* arr = "013##4##25##6##";
PostThread_BiTree tree(arr, strlen(arr)); //构建三叉树
tree.PostTreading();
tree.PostOrder();//arr 3 4 1 5 6 2 0
cout << endl << "______________________" << endl;
char* arr1 = "013##4##2#56###";
char* arr2 = "12#3##4##";
PostThread_BiTree tree1(arr2, strlen(arr2));
tree1.PostTreading();
tree1.PostOrder();
cout << endl << "______________________" << endl;
char* arr3 = "12#3#4##5##";
PostThread_BiTree tree2(arr3, strlen(arr3));
tree2.PostTreading();
tree2.PostOrder();
cout << endl << "______________________" << endl;
char* arr4 = "126##3#4##5##";
PostThread_BiTree tree3(arr4, strlen(arr4));
tree3.PostTreading();
tree3.PostOrder();
cout << endl << "______________________" << endl;
}
int main()
{
Test();
return 0;
}