后序线索化二叉树及遍历(图解)
上一篇博客对于 二叉树线索化以及线索化的先序、中序、后序遍历做了比较详细的描述
写在前面
其实,我还是很想把本篇博客和二叉树的线索化写在一块的,但是考虑到可能这博客的内容就看足以超过了上一篇的篇幅,考虑到读者可能会疲乏,而且这篇也是线索二叉树中最难的了(查阅了很多网上的资料也鲜有人来讲述后序线索二叉树的遍历,有的就算有也只是把代码放在那里,理解 对于初学者还是有点困难的)
构建节点(多了双亲节点节点)
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判断,而是用Rtagif (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判断,而是用Rtagif (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 0cout << 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;
}
后序线索化二叉树及遍历(图解)相关推荐
- Java实现前中后序线索化二叉树以及遍历
文章目录 一.线索化二叉树的原理 二.构建线索化二叉树 三.代码实现线索二叉树 一.线索化二叉树的原理 在前面介绍二叉树的文章中提到,二叉树可以使用两种存储结构:顺序存储和链式存储,在使用链式存储时, ...
- Java:中序线索化二叉树及遍历
class Threade{BinaryTree root;//记录根节点,用于遍历BinaryTree pre;//pre指针,用于线索化,表示上一个节点Threade(BinaryTree nod ...
- 线索化二叉树及其遍历
线索化二叉树及其遍历 线索二叉树基本介绍 1.利用二叉表中空指针域,存放指向该结点在某种遍历次序下的前驱与后续节点的指针称为线索 2.这种加上了线索的二叉链表称为线索链表,相应的二叉树也称为线索二叉树 ...
- 数据结构2:中序线索化二叉树为什么要通过pre设置后继结点
在听尚硅谷韩顺平老师课程的时候这个地方没有理解,先把java中序线索化二叉树代码附上: private HeroNode pre = null;//在递归线索化,pre总是保留前一个结点 /**** ...
- node 获取表单数据 为空_程序员:数据结构和算法,中序线索化二叉树
1.中序线索化二叉树 创建如上的二叉树,线索化二叉树时,根据指定的遍历方式得到的节点的访问顺序,一个节点前面的节点,叫做前驱节点,一个节点后面的节点,叫做后继节点. 线索化二叉树的规则: ...
- 中序线索化二叉树c语言实现
```c #include<stdio.h>//首先定义一个遍历前驱的节点ThreadNode *pre = NULL;//指向前驱节点typedef struct ThreadNode ...
- 线索化二叉树及遍历_笔记
线索化二叉树能够充分使用空余的left和right指针,left放前驱,right放后继指针: 一.中序线索化 1.实现思路:正常的中序思想,只不过中间实现前驱和后继节点的指向,为了确定前驱节点需要使 ...
- 【算法系列之线索化二叉树,前序线索化、中序线索化、后序线索化以及遍历~】
1.何谓线索化二叉树 2.线索化二叉树的本质 3.线索化二叉树的存储结构 4.构建线索化二叉树 4.1.先序线索化 4.2.中序线索化 4.3.后序线索化 5.遍历线索化二叉树 5.1.先序遍历 先序 ...
- C语言实现线索化二叉树(先序、中序、后序)
>>如何用C语言构建一颗二叉树? 第一种方法: ThreadTree A = (ThreadTree)malloc(sizeof(ThreadNode));A->data = { ' ...
最新文章
- 【HDOJ】3487 Play with Chain
- 【转】C#生成验证码
- 动力节点老杜mysql文件_mysql主从复制+mysql主从复制延迟解决方案
- ArrayList实现原理
- 如何在64位的Win10系统下安装.NET Framework 3.0
- Duboo入门示例(Idea开发环境)
- chap6_2 Parallax mapping in OGRE
- 7.python的字符串处理常见方法——《深入python3》
- 为suse 12.3桌面系统安装金山WPS OFFICE
- 使用番茄助手 快速注释
- Blender3.0资产浏览器
- .NET 开源项目概览
- AVRWARE++开发笔记8:Atmel Studio去除拼写检查
- 大部分erp系统都是java和.net甚至还有asp,为什么鲜有php的erp?
- xampp control-panel深深的坑
- java ftp主动模式和被动模式_FTP 的主动模式和被动模式
- 【SpringBoot】‘parent.relativePath‘ of POM points at instead of, please verify your project structure
- open-falcon分布式安装
- Linux下编译so文件
- Javascript在线调试安卓工具的实现