1、什么是线索二叉树
线索化的二叉树就是:在原有的二叉树基础上有些改动,将没有孩子结点的链域声明为线,左孩子指向前驱,右孩子指向后继节点;
有孩子结点的为链,表示指向原先的左右孩子;
线索二叉树的基本存储结构如下:
2、中序二叉树的图形表示
线索二叉树无需遍历,可以很方便的得到其任一结点的前驱、后继。+
3、中序线索二叉树的建立
必须先建立好二叉树(根据先序序列),在其基础上创建中序线索二叉树;
核心程序:最好画图跟踪一下,才能弄得清楚;
注意:最后一个结点在函数结束时为LINK,没有更改过来!
templatevoid BinTree ::createInThread(BinTreeNode *t, BinTreeNode *&pre){ //创建中序线索二叉树 if(t == NULL){ //pre必须引用传递,的保证及时的更改!!! return; //空树直接返回 } createInThread(t->leftChild, pre); //pre一直为空,一直在往左走; if(t->leftChild == NULL){ t->ltag = THREAD; //将左孩子设置为线 t->leftChild = pre; //因为是第一个,无前驱,所以置空 } if(pre != NULL && pre->rightChild == NULL){ pre->rtag = THREAD; //将右孩子设置为线; pre->rightChild = t; //此时指向后继结点,t已经回到了上一层 } pre = t; //将当前结点给pre; createInThread(t->rightChild, pre); //往右边递归 }
完整创建程序:
#ifndef _THREAD_BIN_TREE_H_ #define _THREAD_BIN_TREE_H_ #includeusing namespace std; typedef enum{LINK, THREAD}TAG; //定义枚举标记链和线 template class BinTree; template //结点类,多了两个标记链和线的; class BinTreeNode{ friend class BinTree ; public: BinTreeNode() : data(Type()), leftChild(NULL), rightChild(NULL), ltag(LINK), rtag(LINK){} BinTreeNode(Type value, BinTreeNode *left = NULL, BinTreeNode *right = NULL) : data(value), leftChild(left), rightChild(right), ltag(LINK), rtag(LINK){} ~BinTreeNode(){} private: Type data; BinTreeNode *leftChild; BinTreeNode *rightChild; TAG ltag; //左标记 TAG rtag; //右标记 }; /////////////////////////////////////////////////////////////////////////////// template class BinTree{ public: BinTree() : root(NULL){} BinTree(Type ref) : root(NULL), refval(ref){} BinTree(const BinTree &t){} ~BinTree(){ } public: void createBinTree(const char *str); //的先建立二叉树 void createInThread(); protected : void createBinTree(const char *&str, BinTreeNode *&t); void createInThread(BinTreeNode *t, BinTreeNode *&pre); template void BinTree ::createBinTree(const char *str){ createBinTree(str, root); } template void BinTree ::createInThread(){ //在二叉树已经建立起来,创建中序线索二叉树; BinTreeNode *pre = NULL; //得弄一个前驱节点,做为参数传递过去 createInThread(root, pre); //真正的创建中序线索二叉树 pre->rtag = THREAD; //最后一个应该为线 } template void BinTree ::createInThread(BinTreeNode *t, BinTreeNode *&pre){ //创建中序线索二叉树 if(t == NULL){ return; } createInThread(t->leftChild, pre); if(t->leftChild == NULL){ t->ltag = THREAD; t->leftChild = pre; } if(pre != NULL && pre->rightChild == NULL){ pre->rtag = THREAD; pre->rightChild = t; } pre = t; createInThread(t->rightChild, pre); } template //创建二叉树 void BinTree ::createBinTree(const char *&str, BinTreeNode *&t){ if(*str == refval){ t = NULL; }else{ t = new BinTreeNode (*str); createBinTree(++str, t->leftChild); createBinTree(++str, t->rightChild); } } #endif
4、其它方法的实现:
中序线索二叉树
public: BinTreeNode* first()const; //查找中序的第一个结点 BinTreeNode * last()const; //查找中序的最后一个结点 BinTreeNode * prev(BinTreeNode *cur)const; //查找当前结点的前驱 BinTreeNode * next(BinTreeNode *cur)const; //查找当前结点的后继 BinTreeNode * parent(BinTreeNode *cur)const; //查找当前结点的父结点 void inOrder()const; //中序遍历线索二叉树 BinTreeNode * find(const Type &key); //查找某一结点
关于还有些方法: 求树高,求结点个数,这些其实跟前面写的差不多,将结束条件换为if(t->ltag == THREAD) return 0;
(1)、查找第一个结点
templateBinTreeNode * BinTree ::first(BinTreeNode *t)const{ if(t == NULL){ return NULL; } while(t->ltag == LINK){ t = t->leftChild; } return t; }
(2)、查找最后一个结点
templateBinTreeNode * BinTree ::last(BinTreeNode *t)const{ if(t == NULL){ return NULL; } while(t->rtag == LINK){ t = t->rightChild; } return t; }
(3)、查找当前结点的前驱:
templateBinTreeNode * BinTree ::prev(BinTreeNode *t, BinTreeNode *cur)const{ if(t == NULL || cur == NULL){ return NULL; } if(cur->ltag == THREAD){ return cur->leftChild; }else{ return last(cur->leftChild); //当前结点的前驱是:左树的最后一个结点; } }
(4)、查找当前结点的后继
templateBinTreeNode * BinTree ::next(BinTreeNode *t, BinTreeNode *cur)const{ if(t == NULL || cur == NULL){ return NULL; } if(cur->rtag == THREAD){ return cur->rightChild; }else{ return first(cur->rightChild); //当前结点的后继是:右树的第一个结点; } }
(5)、中序遍历线索化二叉树
templatevoid BinTree ::inOrder(BinTreeNode *t)const{ BinTreeNode *p; if(t == NULL){ return; } for(p = first(t); p != NULL; p = next(t, p)){ cout< data<<" "; } cout< (6)、查找某一结点
templateBinTreeNode * BinTree ::find(BinTreeNode *t, const Type &key){ if(t == NULL){ return NULL; } if(t->data == key){ return t; } BinTreeNode *p; for(p = first(t); p != NULL; p = next(t, p)){ if(p->data == key){ return p; } } return NULL; } (7) 、查找当前结点的父结点,分析如下:
1、为空,或当前为根结点,其父----->NULL
2、看看根是否为父结点;
3、就是图中E、D这种情况,其父----->后继结点
4、就是图中H、G这种情况,其父----->前驱结点
以上就是针对存在线的求法;
5、针对没有线的求法:(一)、例如求D:看的是其右的最后一个,因为线,走了一圈,就是确定B是其父;
(二)、找当前结点的左树的第一个,在返回其左孩子(此时这个线就是父节点);templateBinTreeNode * BinTree ::parent(BinTreeNode *t, BinTreeNode *cur)const{ if(t == NULL || cur == NULL || cur == t){ return NULL; //父为空 } if(t->ltag == LINK && t->leftChild == cur){ //父为根节点 return t; } if(t->rtag == LINK && t->rightChild == cur){ return t; } if(cur->rtag == THREAD && cur->rightChild->leftChild == cur){ //线的找 return cur->rightChild; } if(cur->ltag == THREAD && cur->leftChild->rightChild == cur){ //线的找 return cur->leftChild; } BinTreeNode *p = last(cur->rightChild); //往右找最后一个, p = p->rightChild; if(p != NULL && p->leftChild->rightChild == cur){ return p->leftChild; } p = first(cur->leftChild); //换换思路,往左找第一个。 return p->leftChild; }
5、完整代码、调试程序,测试结果
(1)、代码
#ifndef _THREAD_BIN_TREE_H_ #define _THREAD_BIN_TREE_H_ #includeusing namespace std; typedef enum{LINK, THREAD}TAG; template class BinTree; template class BinTreeNode{ friend class BinTree ; public: BinTreeNode() : data(Type()), leftChild(NULL), rightChild(NULL), ltag(LINK), rtag(LINK){} BinTreeNode(Type value, BinTreeNode *left = NULL, BinTreeNode *right = NULL) : data(value), leftChild(left), rightChild(right), ltag(LINK), rtag(LINK){} ~BinTreeNode(){} private: Type data; BinTreeNode *leftChild; BinTreeNode *rightChild; TAG ltag; //左标记 TAG rtag; //右标记 }; /////////////////////////////////////////////////////////////////////////////// template class BinTree{ public: BinTree() : root(NULL){} BinTree(Type ref) : root(NULL), refval(ref){} BinTree(const BinTree &t){} ~BinTree(){ } public: void createBinTree(const char *str); void createInThread(); public: BinTreeNode * first()const; BinTreeNode * last()const; BinTreeNode * prev(BinTreeNode *cur)const; BinTreeNode * next(BinTreeNode *cur)const; BinTreeNode * parent(BinTreeNode *cur)const; void inOrder()const; BinTreeNode * find(const Type &key); protected: BinTreeNode * first(BinTreeNode *t)const; BinTreeNode * last(BinTreeNode *t)const; BinTreeNode * prev(BinTreeNode *t, BinTreeNode *cur)const; BinTreeNode * next(BinTreeNode *t, BinTreeNode *cur)const; BinTreeNode * parent(BinTreeNode *t, BinTreeNode *cur)const; void inOrder(BinTreeNode *t)const; BinTreeNode * find(BinTreeNode *t, const Type &key); protected : void createBinTree(const char *&str, BinTreeNode *&t); void createInThread(BinTreeNode *t, BinTreeNode *&pre); private: BinTreeNode *root; Type refval; //'#' }; template void BinTree ::createBinTree(const char *str){ createBinTree(str, root); } template void BinTree ::createInThread(){ BinTreeNode *pre = NULL; createInThread(root, pre); pre->rtag = THREAD; //最后一个应该为线 } template BinTreeNode * BinTree ::first()const{ return first(root); } template BinTreeNode * BinTree ::last()const{ return last(root); } template BinTreeNode * BinTree ::prev(BinTreeNode *cur)const{ return prev(root, cur); } template BinTreeNode * BinTree ::next(BinTreeNode *cur)const{ return next(root, cur); } template BinTreeNode * BinTree ::parent(BinTreeNode *cur)const{ return parent(root, cur); } template void BinTree ::inOrder()const{ inOrder(root); } template BinTreeNode * BinTree ::find(const Type &key){ return find(root, key); } ////////////////////////////////////////////////////////////////////////////////////////// template BinTreeNode * BinTree ::find(BinTreeNode *t, const Type &key){ if(t == NULL){ return NULL; } if(t->data == key){ return t; } BinTreeNode *p; for(p = first(t); p != NULL; p = next(t, p)){ if(p->data == key){ return p; } } return NULL; } template void BinTree ::inOrder(BinTreeNode *t)const{ BinTreeNode *p; if(t == NULL){ return; } for(p = first(t); p != NULL; p = next(t, p)){ cout< data<<" "; } cout< BinTreeNode * BinTree ::parent(BinTreeNode *t, BinTreeNode *cur)const{ if(t == NULL || cur == NULL || cur == t){ return NULL; } if(t->ltag == LINK && t->leftChild == cur){ return t; } if(t->rtag == LINK && t->rightChild == cur){ return t; } if(cur->rtag == THREAD && cur->rightChild->leftChild == cur){ return cur->rightChild; } if(cur->ltag == THREAD && cur->leftChild->rightChild == cur){ return cur->leftChild; } BinTreeNode *p = last(cur->rightChild); p = p->rightChild; if(p != NULL && p->leftChild->rightChild == cur){ return p->leftChild; } p = first(cur->leftChild); return p->leftChild; } template BinTreeNode * BinTree ::next(BinTreeNode *t, BinTreeNode *cur)const{ if(t == NULL || cur == NULL){ return NULL; } if(cur->rtag == THREAD){ return cur->rightChild; }else{ return first(cur->rightChild); } } template BinTreeNode * BinTree ::prev(BinTreeNode *t, BinTreeNode *cur)const{ if(t == NULL || cur == NULL){ return NULL; } if(cur->ltag == THREAD){ return cur->leftChild; }else{ return last(cur->leftChild); } } template BinTreeNode * BinTree ::last(BinTreeNode *t)const{ if(t == NULL){ return NULL; } while(t->rtag == LINK){ t = t->rightChild; } return t; } template BinTreeNode * BinTree ::first(BinTreeNode *t)const{ if(t == NULL){ return NULL; } while(t->ltag == LINK){ t = t->leftChild; } return t; } template void BinTree ::createInThread(BinTreeNode *t, BinTreeNode *&pre){ if(t == NULL){ return; } createInThread(t->leftChild, pre); if(t->leftChild == NULL){ t->ltag = THREAD; t->leftChild = pre; } if(pre != NULL && pre->rightChild == NULL){ pre->rtag = THREAD; pre->rightChild = t; } pre = t; createInThread(t->rightChild, pre); } template void BinTree ::createBinTree(const char *&str, BinTreeNode *&t){ if(*str == refval){ t = NULL; }else{ t = new BinTreeNode (*str); createBinTree(++str, t->leftChild); createBinTree(++str, t->rightChild); } } #endif (2)、测试代码
#include"threadBinTree.h" int main(void){ char *str = "ABC##DE##F##G#H##"; BinTreebt('#'); bt.createBinTree(str); bt.createInThread(); bt.inOrder(); BinTreeNode *k = bt.find('A'); //直接输入字符查找,其方法find(const Type &key)中的const万万不可少 BinTreeNode *p = bt.first(); //C printf("%p\n", k); //A BinTreeNode *m; m = bt.parent(p); // printf("%p\n", m); //B BinTreeNode *n; n = bt.parent(m); printf("%p\n", n); //A return 0; } (3)、测试结果