线索二叉树的先序、中序、后序遍历
来源:互联网 发布:unity3d制作2d游戏教程 编辑:程序博客网 时间:2024/05/16 00:33
线索化二叉树:
当某个节点的左孩子为空时,将_pLeft指针指向他的前一个节点;
当某个节点的右孩子为空时,将_pRight指针指向它的后一个结点。
根据遍历方式不同,得到的前后节点也不同,线索化二叉树分为三种不同的情况:
先序遍历线索化二叉树
中序遍历线索化二叉树
后序遍历线索化二叉树
线索二叉树与普通二叉树有什么区别呢?线索化二叉树中空的指针域至多2个,至少1个;
普通二叉树中空的指针域是n+1个,n(节点数)。
所以能够有效地利用资源,并且在遍历时不用递归和栈结构也可以遍历。
为了区别两个节点的关系是双亲-孩子节点,还是前驱-后继节点,可以在每个节点创建时 ,增加两个成员变量,_leftThread和_rightThread,这两个变量只有两种状态,LINK(双亲-孩子)、THREAD(前驱=后继)。
#include <iostream>#include <windows.h>#include <string.h>using namespace std;enum PointIhfo{ LINK, THREAD};template <class T>struct BinaryTreeNodeThd//定义二叉树的节点{ BinaryTreeNodeThd(const T& value) :_value(value) ,_pLeft(NULL) ,_pRight(NULL) ,_pParent(NULL) , _leftThread(LINK) , _rightTrhead(LINK) {} T _value; BinaryTreeNodeThd<T>* _pLeft; BinaryTreeNodeThd<T>* _pRight; BinaryTreeNodeThd<T>* _pParent; PointIhfo _leftThread; PointIhfo _rightTrhead;};
template<class T>class BinaryTreeThd{ typedef BinaryTreeNodeThd<T> Node;public: BinaryTreeThd() :_pRoot(NULL) {} BinaryTreeThd(const T arr[], size_t size, const T& invalid) { size_t index=0; _CreateBinaryTree(_pRoot, NULL, arr, size, index, invalid); } BinaryTreeThd(const BinaryTreeThd<T>& bt) { _pRoot = _CopyBinaryTree(bt._pRoot); } BinaryTreeThd<T>& operator=(const BinaryTreeThd<T>& bt) { if(this != &bt) { _DestroyBinaryTree(_pRoot); _pRoot = _CopyBinaryTree(bt._pRoot); } return *this; } ~BinaryTreeThd() { _DestroyBinaryTree(_pRoot); } 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() { if(_pRoot == NULL) return; Node* pCur = _pRoot; while(pCur) { while(pCur->_leftThread == LINK)//访问到最左结点 { cout<<pCur->_value<<" "; pCur = pCur->_pLeft; } cout<<pCur->_value<<" ";//访问最左边的节点 while(pCur->_rightTrhead == THREAD)//如果该结点没有右孩子,则一直访问 { pCur = pCur->_pRight; cout<<pCur->_value<<" "; } if(pCur->_leftThread == LINK)//如果该结点有左孩子,则访问左孩子 pCur = pCur->_pLeft; else //否则访问右孩子 pCur = pCur->_pRight; } } void InOrder() { if(_pRoot == NULL) return; Node* pCur = _pRoot; while(pCur) { while(pCur->_leftThread == LINK)//找最左节点 pCur = pCur->_pLeft; cout<<pCur->_value<<" ";//访问最左结点 while(pCur->_rightTrhead == THREAD)//如果该结点没有右孩子,则一直访问该节点 { pCur = pCur->_pRight; cout<<pCur->_value<<" "; } pCur = pCur->_pRight;//如果该结点有右孩子,则访问右孩子 } } void PostOrder() { if(_pRoot == NULL) return; Node* pCur = _pRoot; Node* pPre = NULL; while(pCur) { while(pCur->_leftThread == LINK)//找到最左结点 pCur = pCur->_pLeft; while(pCur && pCur->_rightTrhead == THREAD)//如果最左结点存在且它的右孩子 { //不存在,就一直访问它的右孩子 cout<<pCur->_value<<" "; pPre = pCur; //将当前节点保存 pCur = pCur->_pRight; } while(pCur && pCur->_pRight == pPre) //如果当前节点的右孩子刚刚被访问,就访问当前节点 { cout<<pCur->_value<<" "; pPre = pCur; pCur = pCur->_pParent; } if(pCur && pCur->_rightTrhead == LINK)//如果当前节点的右孩子存在,就访问它的右孩子 pCur = pCur->_pRight; } }private: void _CreateBinaryTree(Node* &pRoot, Node* pParent, const T arr[], size_t size, size_t& index, const T& invalid) { if(index<size && arr[index] != invalid) { //创建根节点 pRoot = new Node(arr[index]); pRoot->_pParent = pParent; //创建左子树 _CreateBinaryTree(pRoot->_pLeft, pRoot, arr, size, ++index, invalid); pRoot->_leftThread = LINK; //创建右子树 _CreateBinaryTree(pRoot->_pRight, pRoot, arr, size, ++index, invalid); pRoot->_rightTrhead = LINK; } } Node* _CopyBinaryTree(Node* pRoot) { Node* pNode = NULL; if(pRoot) { pNode = new Node(pRoot->_value); pNode->_pLeft = _CopyBinaryTree(pRoot->_pLeft); pNode->_leftThread = pRoot->_leftThread; pNode->_pParent = pRoot->_pParent; pNode->_pRight = _CopyBinaryTree(pRoot->_pRight); pNode->_rightTrhead = pRoot->_rightTrhead; pNode->_pParent = pRoot->_pParent; } return pNode; } void _DestroyBinaryTree(Node*& pRoot) { if(pRoot) { _DestroyBinaryTree(pRoot->_pLeft); _DestroyBinaryTree(pRoot->_pRight); delete pRoot; pRoot = NULL; } } void _PreThread(Node* pRoot, Node*& prev) { if(pRoot == NULL) return; if(pRoot->_pLeft == NULL) { pRoot->_pLeft = prev; pRoot->_leftThread = THREAD; } if(prev && prev->_pRight == NULL) { prev->_pRight = pRoot; prev->_rightTrhead = THREAD; } prev = pRoot; if(pRoot->_leftThread == LINK) _PreThread(pRoot->_pLeft, prev); if(pRoot->_rightTrhead == LINK) _PreThread(pRoot->_pRight, prev); } void _InThread(Node* pRoot, Node*& prev) { if(pRoot == NULL) return; //左子树 if(pRoot->_leftThread == LINK) _InThread(pRoot->_pLeft, prev); if(pRoot->_pLeft == NULL) { pRoot->_pLeft = prev; pRoot->_leftThread = THREAD; } if(prev && prev->_pRight == NULL) { prev->_pRight = pRoot; prev->_rightTrhead = THREAD; } prev = pRoot; //右子树 if(pRoot->_rightTrhead == LINK) _InThread(pRoot->_pRight, prev); } void _PostThread(Node* pRoot, Node*& prev) { if(pRoot == NULL) return; //左子树 if(pRoot->_leftThread == LINK) _PostThread(pRoot->_pLeft, prev); //右子树 if(pRoot->_rightTrhead == LINK) _PostThread(pRoot->_pRight, prev); if(pRoot->_pLeft == NULL) { pRoot->_pLeft = prev; pRoot->_leftThread = THREAD; } if(prev && prev->_pRight == NULL) { prev->_pRight = pRoot; prev->_rightTrhead = THREAD; } prev = pRoot; }private: Node* _pRoot;//根节点};int main(){ char* arr = "124##5##3#6"; BinaryTreeThd<char> bt1(arr, strlen(arr), '#'); //bt1.PreThread(); //bt1.PreOrder(); //bt1.InThread(); //bt1.InOrder(); bt1.PostThread(); bt1.PostOrder(); //BinaryTreeThd<char> bt2(bt1); system("pause"); return 0;}
0 0
- 二叉树的线索化以及 线索化的先序,中序,后序遍历
- 二叉树线索化以及线索化的先序、中序、后序遍历
- 先序遍历/后序遍历创建线索二叉树
- 线索二叉树的先序、中序、后序遍历
- 树:二叉树的集中遍历方法(先序,中序,后序遍历,线索二叉树)
- 后序二叉线索树的遍历
- 线索化中序、先序、后序遍历二叉树的方式(待补充完整)
- 线索二叉树(先序,中序,后序)
- 先序 中序 后序 线索二叉树
- 先序,中序,后序线索化二叉树
- 线索二叉树的中序遍历
- 中序线索二叉树的创建、线索化和遍历(前序遍历和后序遍历)
- 线索二叉树的实现 先序 中序 后序
- 二叉树的遍历(先序、中序、后序)
- 二叉树的先序、中序、后序遍历
- 二叉树的遍历:先序、中序、后序
- 二叉树的先序、中序、后序遍历
- 二叉树的先序、中序、后序遍历
- C#实现通过模板自动创建Word文档的方法
- (三)简单工厂模式详解
- [蓝桥杯]算法训练 操作格子-链式线段树
- linux命令笔记(一)
- tesseract_ocr 字符识别基础及训练字库、合并字库
- 线索二叉树的先序、中序、后序遍历
- caffe编译与安装过程中的疑难点
- Java中new File("."),new File(""),new File(".."),new File(".\\")的区别
- storm '*/stormconf.ser' does not exist 问题nimbus进程刚启动后就自动退出
- Linux中安装jdk的三种方式
- Maven 安装 以及 eclipse 配置Maven 插件
- Tesseract-OCR4.0版本在VS2015上的编译与运行
- HDU6025-Coprime Sequence
- [FAQ19483][SAT]双卡情况下如何显示两个STK icon图标