线索化二叉树的创建及遍历
来源:互联网 发布:iphone自动切换网络 编辑:程序博客网 时间:2024/06/05 23:55
#include<stdio.h>#include<iostream>using namespace std;enum thread{ LINK, THREAD,};template<class T>struct BinaryTreeThdNode{ BinaryTreeThdNode() :_pLeft(NULL) ,_pRight(NULL) ,_pParent(NULL) ,_leftThread(LINK) ,_rightThread(LINK) {} T _data; BinaryTreeThdNode* _pLeft;//左孩子 BinaryTreeThdNode* _pRight;//右孩子 BinaryTreeThdNode* _pParent;//双亲节点 enum thread _leftThread;//左索引 enum thread _rightThread;//右索引};template<class T>class BinaryTreeThd{public: typedef BinaryTreeThdNode<T> Node; BinaryTreeThd()//线索二叉树的构造 :_pRoot(NULL) {} BinaryTreeThd(const T array[],size_t size,T invalid)//线索二叉树的构造 { size_t index=0; _pRoot = _CreateTree(_pRoot,array,size,index,invalid);//二叉树的创建 } void PreThreading()//前序线索化 { Node* prev = NULL; _PreThreading(_pRoot,prev); } void InThreading()//中序线索化 { Node* prev = NULL; _InThreading(_pRoot,prev); } void PostThreading()//后序线索化 { Node* prev = NULL; _PostThreading(_pRoot,prev); } void PreOrder() { // 找最左边的节点并访问路径上的节点---访问该最左节点---判断右子树是否为NULL,若为NULL,访问连续后继节点 //若不为NULL,则pCur=pCur->_pRight将右子树重新作为一棵树进行访问 if(_pRoot==NULL) return; Node* pCur = _pRoot; while(pCur) { while(pCur->_leftThread == LINK) { cout<<pCur->_data<<" "; pCur = pCur->_pLeft; } cout<<pCur->_data<<" "; //while(pCur->_rightThread == THREAD)// 判断该节点的右子树不存在,访问后继节点 //{ // pCur = pCur->_pRight; // cout<<pCur->_data<<" "; //} //if(pCur->_leftThread == LINK)//再访问完后继结点后,可能有两种情况,存在左子树,则先访问左子树,当作新树来处理 //{ // pCur = pCur->_pLeft; //} //if(pCur->_rightThread == LINK)//再访问完后继节点,可能没有左子树,只有右子树,或则最左节点右子树存在,则当作新树处理 //{ // pCur = pCur->_pRight; //} //代码优化---将上面注释起来的代码用下面一句代码替换 pCur = pCur->_pRight;//全部当作新的树来处理 } } void InOrder()//中序线索化二叉树的中序遍历 { // 找到最左端的节点,不访问路径,找到之后访问最左端的节点---再判断其有无右子树,若有,作为新树去处理,若没有,连续访问其后继节点 if(_pRoot==NULL) return; Node* pCur = _pRoot; while(pCur) { while(pCur->_leftThread == LINK) { pCur = pCur->_pLeft; } cout<<pCur->_data<<" "; while(pCur->_rightThread == THREAD) { pCur = pCur->_pRight; cout<<pCur->_data<<" "; } pCur = pCur->_pRight; } } void PostOrder()//后序线索化二叉树的后序遍历 { //找到最左节点,不访问,首先判断该节点的右子树是否存在,若不存在,访问该节点并到其后继节点,若存在,则访问右子树 //单纯的这样写,会导致死循环问题,在3的地方,原因是6已经访问过了,但pCur=pCur->_pRight还是指向6,接着访问6和3,死循环---解决办法prev标记访问过的 //仅仅是标记过了还是有问题,1没有办法访问到---解决办法,设立双亲节点 //特殊的索引树--左单枝问题,根节点没有访问(最后一个节点的右索引是LINK)---解决办法,if判断 //左单支问题 if(_pRoot==NULL) return; Node* pCur = _pRoot; Node* prev = NULL;//标记访问过的节点 while(pCur) { while(pCur->_leftThread == LINK && pCur->_pRight != prev) pCur = pCur->_pLeft; while(pCur->_rightThread == THREAD) { cout<<pCur->_data<<" "; prev = pCur; pCur = pCur->_pRight; } if(pCur==_pRoot && pCur->_pRight==NULL) { cout<<pCur->_data<<" "; return ; } while(pCur && pCur->_pRight==prev) { cout<<pCur->_data<<" "; prev = pCur; pCur = pCur->_pParent; } if(pCur && pCur->_pRight != prev) pCur = pCur->_pRight; } }private: //底层实现 Node* _CreateTree(Node* pRoot,const T array[],size_t size,size_t& index,T& invalid)//二叉树的创建 { if(index<size && array[index]!=invalid) { pRoot = new Node; pRoot->_data = array[index]; pRoot->_pLeft = _CreateTree(pRoot->_pLeft,array,size,++index,invalid); if(pRoot->_pLeft) pRoot->_pLeft->_pParent = pRoot; pRoot->_pRight = _CreateTree(pRoot->_pRight,array,size,++index,invalid); if(pRoot->_pRight) pRoot->_pRight->_pParent = pRoot; } return pRoot; } void _PreThreading(Node* pRoot,Node*& prev)//前序线索化---采用先线索化根节点,判断根节点左右子树是否存在,再利用递归线索化左子树和右子树的的节点 { if(pRoot) { if(pRoot->_pLeft == NULL)// 线索化当前指针的左指针域 { pRoot->_pLeft = prev; pRoot->_leftThread = THREAD; } if(prev!=NULL && prev->_pRight==NULL)//线索化前一个节点的右指针域 { prev->_pRight = pRoot; prev->_rightThread = THREAD; } prev=pRoot; if(pRoot->_leftThread != THREAD)//防止索引后陷入死循环 _PreThreading(pRoot->_pLeft,prev); if(pRoot->_rightThread != THREAD) _PreThreading(pRoot->_pRight,prev); } } void _InThreading(Node* pRoot,Node*& prev)//中序线索化 { if(pRoot) { _InThreading(pRoot->_pLeft,prev);//找到最左边的节点 if(pRoot->_pLeft==NULL)//线索化该节点的左指针域 { pRoot->_pLeft = prev; pRoot->_leftThread = THREAD; } if(prev && prev->_pRight==NULL)//线索化前一个节点的右指针域 { prev->_pRight = pRoot; prev->_rightThread = THREAD; } prev = pRoot;//该节点的左指针域线索完毕,标记该节点, if(pRoot->_rightThread != THREAD) _InThreading(pRoot->_pRight,prev);//线索化右子树的节点 } } void _PostThreading(Node* pRoot,Node*& prev)//测试二叉树的后续索引 { if(pRoot) { _PostThreading(pRoot->_pLeft,prev); _PostThreading(pRoot->_pRight,prev); if(pRoot->_pLeft == NULL) { pRoot->_pLeft = prev; pRoot->_leftThread = THREAD; } if(prev && prev->_pRight==NULL) { prev->_pRight = pRoot; prev->_rightThread = THREAD; } prev = pRoot; } }private: Node* _pRoot;};
测试代码
void funtest(){ char str[] = {"124###35##6"}; char invalid = '#'; BinaryTreeThd<char> t; BinaryTreeThd<char> t1(str,strlen(str),invalid);//测试线索二叉树的创建 //t1.PreThreading();//测试线索二叉树的先序索引 //t1.InThreading();//测试线索二叉树的中序索引 //t1.PostThreading();//测试线索二叉树的后序线索}void funtest1()//测试前序索引二叉树的前序遍历{ char str[] = {"124###35##6"}; char invalid = '#'; BinaryTreeThd<char> t; BinaryTreeThd<char> t1(str,strlen(str),invalid); t1.PreThreading(); t1.PreOrder();}void funtest2()//测试中序索引二叉树的中序遍历{ char str[] = {"124###35##6"}; char invalid = '#'; BinaryTreeThd<char> t; BinaryTreeThd<char> t1(str,strlen(str),invalid);//测试线索二叉树的创建 t1.InThreading(); t1.InOrder();}void funtest3()//测试后序索引二叉树的后序遍历{ //char str[] = {"124###35##6"}; char str[] = {"12#3##45#6#7##8"}; char invalid = '#'; BinaryTreeThd<char> t; BinaryTreeThd<char> t1(str,strlen(str),invalid);//测试线索二叉树的创建 t1.PostThreading(); t1.PostOrder();}int main(){ //funtest(); //funtest1(); //funtest2(); funtest3(); getchar(); return 0;}
0 0
- 线索化二叉树的创建及遍历
- 数据结构-线索二叉树的创建及遍历(1)
- 二叉树的创建及线索化
- 线索二叉树的创建极其遍历
- 二叉树的前序中序线索化及对对应线索二叉树的遍历
- 线索二叉树的建立及遍历
- 线索二叉树的生成及遍历
- 线索二叉树的生成及遍历
- 线索化二叉树 前中后序线索化及前序中序遍历
- 线索化二叉树的构造及遍历
- 线索化二叉树、线索二叉树的遍历
- 中序线索二叉树的创建、线索化和遍历(前序遍历和后序遍历)
- 二叉树的遍历及线索二叉树
- 二叉树的建立,遍历,线索化
- 线索化二叉树的建立,遍历
- 线索二叉树的遍历
- 【转】线索二叉树的原理以及创建和遍历
- 线索二叉树的创建、中序遍历、左右插入
- Linux之——bash: warning: setlocale: LC_CTYPE: cannot change locale (EN_US.UTF-8)
- hdoj 2037 今年暑假不AC
- java 连接 Mysql 的连接信息
- I/O字节流
- 设计模式之策略模式
- 线索化二叉树的创建及遍历
- [leetcode: Python]206.Reverse Linked List
- 【GDOI 2017】【JZOJ 1502】小学生语文题
- cannot node find module “” (gulp)
- 开发人员的必备技能
- 使用java开发简单计算器界面,并实现加、减、乘、除运算
- 10.2 运算符重载函数作为类成员函数和友元函数
- Java8内存模型—永久代(PermGen)和元空间(Metaspace)
- 大三上备忘录