线索化二叉树的构造及遍历
来源:互联网 发布:php 7 加密 编辑:程序博客网 时间:2024/05/22 13:52
前言:
二叉树虽然是非线性结构,但二叉树的遍历却为二叉树的结点集导出了一个线性序列。对于 前、中、后序遍历,除了相应序列的第一个结点和最后一个节点,二叉树的遍历序列中每个 结点都有一个前驱和后继结点,但在二叉树中,无法很快的找出按照某种遍历序列该结点的前驱和后继。
在二叉树中希望很快找到某一节点的前驱或后继,而不希望每次都要对二叉树遍历一遍,因此 在创建二叉树的过程中,需要将每个结点的前驱和后继记录下来。我在此处处理的方法是加上一个标记。
enum PiontInfo{LINK,//指向左右孩子THREAD,//指向前驱后继};
结点中指向前驱结点和后继结点的指针称为线索,二叉树结点加上线索的二叉树称为线索 二叉树,对二叉树以某种方式(前序、中序、后续)遍历使其变为线索二叉树的过程称为按 照该方法对二叉树进行线索化
完整的代码如下:
#include<iostream>#include<string.h>using namespace std;enum PiontInfo{LINK,//指向左右孩子THREAD,//指向前驱后继};//节点template<class T>struct BinaryTreeThdNode{BinaryTreeThdNode(const T& value):_value(value),_pLeft(NULL),_pRight(NULL), _parent(NULL),_LeftThread(LINK),_RightThread(LINK){}BinaryTreeThdNode<T>* _pLeft;//左孩子BinaryTreeThdNode<T>* _pRight;//右孩子BinaryTreeThdNode<T>* _parent;//双亲PiontInfo _LeftThread;PiontInfo _RightThread;T _value;};//树template<class T>class BinaryTreeThd{typedef BinaryTreeThdNode<T> Node;public:BinaryTreeThd():_pRoot(NULL){}BinaryTreeThd(const T arr[],size_t size,const T& invalid){size_t index=0; _CreateBinaryTreeThd(_pRoot,arr,size,index,invalid);}//前序线索化void PreThread(){ Node* prev=NULL; _PreThread(_pRoot,prev);}//中序线索化void InThread(){ Node* prev=NULL; _InThread(_pRoot,prev);}//后序线索化void PostThread(){ Node* prev=NULL; _PostThread(_pRoot,prev);} //前序遍历/*思路:找最左边的节点,访问路径上的节点 当前节点:存在右子树 右子树不存在:循环访问后继,*/void PreOrder(){ Node* pCur=_pRoot; while(pCur) { while(LINK==pCur->_LeftThread) { cout<<pCur->_value<<" "; pCur=pCur->_pLeft; } cout<<pCur->_value<<" "; while(THREAD==pCur->_RightThread) { pCur=pCur->_pRight; cout<<pCur->_value<<" "; } if(LINK==pCur->_LeftThread)//左子树存在 pCur=pCur->_pLeft; else //左子树不存在,访问右子树 pCur=pCur->_pRight; }}/*void PreOrder(){ Node* pCur=_pRoot; while(pCur) {while(LINK==pCur->_LeftThread) { cout<<pCur->_value<<" "; pCur=pCur->_pLeft; } cout<<pCur->_value<<" "; pCur=pCur->_pRight; }}*///中序遍历/*思路:找最左边的节点,访问 当前节点的右子树不存在:访问后继 存在:当成树,再次循环访问*/void InOrder(){ Node* pCur=_pRoot; while(pCur) { while(LINK==pCur->_LeftThread) { pCur=pCur->_pLeft; } cout<<pCur->_value<<" "; while(THREAD==pCur->_RightThread) { pCur=pCur->_pRight; cout<<pCur->_value<<" "; } pCur=pCur->_pRight; }}//后序遍历/*思路:找最左边的节点,访问 当前节点的右子树存在,当成树 不存在,访问*/void PostOrder(){ if(NULL==_pRoot) return; Node* pCur=_pRoot; Node* prev=NULL; while(pCur) { //当前节点左子树没有访问 if(prev!=pCur->_pLeft) { while(pCur->_LeftThread==LINK) { pCur=pCur->_pLeft; } } //访问连在一起的后继 while(pCur->_RightThread==THREAD) { cout<<pCur->_value<<" "; prev=pCur; pCur=pCur->_pRight; } //左单支 if(pCur==_pRoot && pCur->_pRight==NULL) { cout<<pCur->_value<<" "; return; } //右单支 while(pCur && pCur->_pRight==prev) { cout<<pCur->_value<<" "; prev=pCur; pCur=pCur->_parent; } //右子树存在 if(pCur && LINK==pCur->_RightThread) { pCur=pCur->_pRight; } }}//-------------------------------------------------------------------private://前序线索化void _PreThread(Node* pRoot ,Node*& prev){ if(pRoot) { //线索化当前节点的左指针域if(NULL==pRoot->_pLeft){pRoot->_pLeft=prev;//指向前驱pRoot->_LeftThread=THREAD;} //线索化上一节点的右指针域if(prev && NULL==prev->_pRight){prev->_pRight=pRoot;//指向后继prev->_RightThread=THREAD;} prev=pRoot;if(LINK==pRoot->_LeftThread) _PreThread(pRoot->_pLeft ,prev);if(LINK==pRoot->_RightThread)_PreThread(pRoot->_pRight ,prev); }}//中序线索化void _InThread(Node* pRoot ,Node*& prev){ if(pRoot) {//左子树_InThread(pRoot->_pLeft ,prev); //线索化当前节点的左指针域if(NULL==pRoot->_pLeft){pRoot->_pLeft=prev;//指向前驱pRoot->_LeftThread=THREAD;} //线索化上一节点的右指针域if(prev && NULL==prev->_pRight){prev->_pRight=pRoot;//指向后继prev->_RightThread=THREAD;} prev=pRoot;//右子树if(LINK==pRoot->_RightThread)_InThread(pRoot->_pRight ,prev); }}//后序线索化void _PostThread(Node* pRoot ,Node*& prev){ if(pRoot) {//左子树_PostThread(pRoot->_pLeft ,prev);//右子树_PostThread(pRoot->_pRight ,prev); //线索化当前节点的左指针域if(NULL==pRoot->_pLeft){pRoot->_pLeft=prev;//指向前驱pRoot->_LeftThread=THREAD;} //线索化上一节点的右指针域if(prev && NULL==prev->_pRight){prev->_pRight=pRoot;//指向后继prev->_RightThread=THREAD;} prev=pRoot; }}//创建树void _CreateBinaryTreeThd(Node*& pRoot,const T arr[],size_t size,size_t &index,const T& invalid){ if(index<size && arr[index]!=invalid) { pRoot=new Node(arr[index]); _CreateBinaryTreeThd(pRoot->_pLeft,arr,size,++index,invalid); if(pRoot->_pLeft) pRoot->_pLeft->_parent=pRoot; _CreateBinaryTreeThd(pRoot->_pRight,arr,size,++index,invalid); if(pRoot->_pRight) pRoot->_pRight->_parent=pRoot; }}private: Node* _pRoot;};
测试代码如下:
#include "BinaryTreeThd.hpp"void Fun1(){char* str="124###35##6";BinaryTreeThd<char> bt(str,strlen(str),'#');/*bt.PreThread();bt.PreOrder();*//*bt.InThread();bt.InOrder();*/bt.PostThread();bt.PostOrder();}int main(){Fun1(); return 0;}
切记:线索化二叉树时有先序,中序和后序,当对二叉树遍历时,也有先序,中序和后序。遍历的方法要和线索化二叉树的方法要一致。
0 0
- 线索化二叉树的构造及遍历
- 二叉树的前序中序线索化及对对应线索二叉树的遍历
- 线索二叉树的建立及遍历
- 线索二叉树的生成及遍历
- 线索二叉树的生成及遍历
- 线索化二叉树 前中后序线索化及前序中序遍历
- 线索化二叉树的创建及遍历
- 线索化二叉树、线索二叉树的遍历
- 二叉树的遍历及线索二叉树
- 二叉树的建立,遍历,线索化
- 线索化二叉树的建立,遍历
- 线索二叉树的遍历
- 16.线索二叉树 (中序) 及 线索二叉树的中序遍历
- 数据结构-线索二叉树的创建及遍历(1)
- 二叉树遍历线索化及树形结构输出
- 后序线索化二叉树及遍历(图解)
- 线索化二叉树(二叉树的简单遍历)
- 二叉树的遍历和线索线索二叉树
- UITextField格式化电话号码和银行卡
- 软件设计原则(二)单一职责原则 -Single Responsibility Principle
- c++作业6
- 深入理解linux下write()和read()函数
- JavaScript 中为 JSON 字符串创建对象
- 线索化二叉树的构造及遍历
- 守护进程(精灵进程)&调用fork一次和两次的区别
- Convolutional Sequence to Sequence Learning
- Bitlocker 参数错误导致打不开移动硬盘的解决方法
- django用户注册
- maven发布时在不同的环境使用不同的配置文件
- CString,string,char*之间的转换(转)
- 欢迎使用CSDN-markdown编辑器
- Java 多线程