线索二叉树,二叉搜索树的简单实现

利用前面的二叉树设计,可以很方便的实现线索二叉树,二叉搜索树,下面给出代码,很多功能还有待添加。
//thread_binary_tree.h
  1 #ifndef _THREAD_BIANTY_TREE_H_
  2 #define _THREAD_BIANTY_TREE_H_
  3 
  4 #include "binary_tree.h"
  5 
  6 namespace binary_tree{
  7 
  8 //ThreadBinaryTreeNode with elem type T
  9 template<typename T>
 10 class ThreadBinaryTreeNode : public BinaryTreeNodeBase< T, ThreadBinaryTreeNode<T> > {
 11     public:
 12         typedef with_thread_node_tag node_category;
 13         ThreadBinaryTreeNode() :m_ltag(0),m_rtag(0) {}
 14         ThreadBinaryTreeNode(const T& elem, ThreadBinaryTreeNode<T> * left = NULL, 
 15                              ThreadBinaryTreeNode<T> * right = NULL,
 16                              bool ltag = 0bool rtag = 0)
 17                 : BinaryTreeNodeBase< T, ThreadBinaryTreeNode<T> > (elem, left, right), 
 18                   m_ltag(ltag), m_rtag(rtag){}
 19         const bool ltag() const{
 20             return m_ltag;
 21         }
 22         const bool rtag() const{
 23             return m_rtag;
 24         }
 25         void set_ltag(bool ltag){
 26             m_ltag = ltag;
 27         }
 28         void set_rtag(bool rtag){
 29             m_rtag = rtag;
 30         }
 31     private:
 32         bool m_ltag;
 33         bool m_rtag;
 34 };
 35 
 36 template <typename U, typename T = ThreadBinaryTreeNode<U> >
 37 class ThreadBinaryTree;
 38 
 39 //到底要不要让穿线二叉树继承BinaryTree呢还是独立一个类
 40 //如果继承,那么要继承所有接口,但是基本上都要重写内容
 41 //我现在只关心一部分内容,提供一部分接口,所以可以独立
 42 //写,这里还是用了继承先,注意使用的时候仅使用那些穿线二叉
 43 //树改写的内容的接口,理论上一个完整的穿线二叉树应该能
 44 //提供BinaryTree的所有接口的,而且这样好复用简单
 45 //也可以单独一个类,以后如果需要添加其它接口,需要BinaryTree
 46 //的实现的化用复合,调用处理。
 47 //其实如ThreadBinaryTree只想继承BinaryTree的一部分,暗示
 48 //BinaryTree的接口太多了,想要继承的是核心接口,应该提出来。
 49 //剩下的可以AdvacedBinaryTree public BinaryTree
 50 //或者剩下的用non memer func
 51 //这里先用private 继承 屏蔽掉基类的接口,恩还是可以用复用
 52 //但是复用代码写起来麻烦些,哦但是那样基类的root()
 53 //用户也没办法用了,还要在thread_tree中明写,权衡,呵呵
 54 //暂时还是public吧, TODO
 55 
 56 //注意对于PrintTree采用了InorderTravel(虚函数重定义)不同的基类triats手法
 57 template <typename U>
 58 class ThreadBinaryTree< U,ThreadBinaryTreeNode<U> > : public BinaryTree<U, ThreadBinaryTreeNode<U> > {
 59     public:
 60         typedef ThreadBinaryTreeNode<U> T;
 61         ~ThreadBinaryTree() { DeleteBinaryTree(this->root()); this->set_root(NULL); } //well 无法访问需要 this->
 62         virtual void DeleteBinaryTree(T *root);
 63         virtual void InOrderTravel(T *root);
 64         virtual void CreateTree(U end_mark) {
 65             BinaryTree<U, ThreadBinaryTreeNode<U> >::CreateTree(end_mark);
 66             //T* p = NULL;
 67             //InThreadRec(this->root(), p);   //no access to m_root directly, 注意InThreadRec(this->root(), NULL)不对
 68             InThreadNoRec(this->root());
 69             cout << "Finished inorder threading" << endl;
 70         }
 71         // TODO
 72 //        virtual void FindElem(T* root, U elem);
 73 //        virtual void PrintTree(); //涉及很多地方要改动
 74 //        virtual void PreOrderTravel();
 75 //        virtual void PostOrderTravel();
 76 //        T* InOrderNext(T *current);
 77 //        T* InOrderPre(T *current);
 78 //        T* PreOrderNext(T *current);
 79 //        void InsertNode(T *pointer, T *newpointer)
 80     private:
 81         //递归中序线索化二叉树
 82         void InThreadRec(T *root, T *&pre);     //这里需要引用.wow!,这里的pre相当一个全局量,而不是随着递归变化的,相当sum
 83         //非递归中序线索化二叉树                //相当容易出错!!!因为要求pre的值及时变化,但如果不是引用,下层变化了,退
 84         void InThreadNoRec(T *root);            //到上层,pre的值又变回到当时的值了(当前栈内)
 85         //中序周游
 86 };
 87 
 88 template <typename U>
 89 void ThreadBinaryTree< U,ThreadBinaryTreeNode<U> > ::
 90 DeleteBinaryTree(ThreadBinaryTreeNode<U> *root) {
 91     cout << "Dlete thread tree" << endl;
 92     if (root) {
 93         if (!root->ltag())
 94             DeleteBinaryTree(root->left());
 95         if (!root->rtag())
 96             DeleteBinaryTree(root->right());
 97         delete root;
 98     }
 99 }
100 //关于二叉中序穿线树就是对于左子树为空的存它在中序遍历的前驱,显然对于中序第一访问的节点没有前驱,这里采用不处理方式
101 //是不行的,因为遍历的时候不方便,也需要把它设置为ltag = 1;
102 //右子树为空则存它在中序遍历的后继,对于中序最后访问的节点,无后继,不特殊处理,所以最后存在两个NULL指针
103 //对于NULL指针也就无所谓去判断是线索还是左右子树了。
104 template <typename U>
105 void ThreadBinaryTree< U,ThreadBinaryTreeNode<U> > ::
106 InThreadRec(ThreadBinaryTreeNode<U> *root, ThreadBinaryTreeNode<U> *&pre) {
107     cout << "Inorder rec threading" << endl;
108     if (root) {
109         InThreadRec(root->left(), pre);
110         if (!root->left()) {
111             root->set_ltag(1);
112             root->set_left(pre);        
113         }
114         if (pre && !pre->right()) {
115             pre->set_rtag(1);
116             pre->set_right(root);
117         }
118         pre = root;
119         InThreadRec(root->right(), pre);
120     }
121 }
122 
123 template <typename U>
124 void ThreadBinaryTree< U,ThreadBinaryTreeNode<U> > ::
125 InThreadNoRec(ThreadBinaryTreeNode<U> *root) {
126     cout << "Inorder threading no rec" << endl;
127     typedef ThreadBinaryTreeNode<U> T;
128     T* p = root;
129     T* pre = NULL;
130     stack<*> s;
131     while(!s.empty() || p) {
132         if (p){
133             s.push(p);
134             p = p->left();
135         } else {
136             p = s.top();
137             if (!p->left()) {
138                 p->set_ltag(1);                   
139                 p->set_left(pre);
140             }
141             if (pre && !pre->right()) {
142                 pre->set_rtag(1);
143                 pre->set_right(p);
144             }
145             pre = p;
146             s.pop();
147             p = p->right();
148         }
149     }
150 }
151 
152 template <typename U>
153 void ThreadBinaryTree< U,ThreadBinaryTreeNode<U> > ::
154 InOrderTravel(ThreadBinaryTreeNode<U> *root) {
155     cout << "Inorder travel thread tree" << endl;
156     typedef ThreadBinaryTreeNode<U> T;
157     T* p = root;
158 //    while (p) {
159 //        if (!p->ltag()) { 
160 //            p = p->left();
161 //        } else {
162 //            Visit(p);
163 //            while (p->rtag()) {
164 //                p = p->right();
165 //                Visit(p);
166 //            }
167 //            p = p->right();     //上面的while 是必要的 不能直接p->right 只有对于原右子为空情况p->right 才进入下一向左状态
168 //        }                       //否则p->right 之后右p->left重复访问左子树了
169 //    }
170     while (p) {
171         while(!p->ltag()) { 
172             p = p->left();          //左子树走
173         } 
174         Visit(p);                  //访问
175         while (p->rtag()) {        //右子树为空,相当不停的pop 访问根节点(左子树已经访问完)
176             p = p->right();        //注意p->right 访问后继的话,证明左子树访问完,要访问右子的,没有继续后继,而不能重复再访问左子
177             Visit(p);
178         }
179         p = p->right();       //OK,进入右子树,重复开始的向左走
180     }                         //上面的while 是必要的 不能直接p->right 只有对于原右子为空情况p->right 才进入下一向左状态
181 }                             //否则p->right 之后右p->left重复访问左子树了
182 
183 
184 
185 //template <typename U, typename T = ThreadBinaryTreeNode<U> >
186 //class ThreadBinaryTree {
187 //    public:
188 //        ThreadBinaryTree() { m_root = NULL;}
189 //        virtual ~ ThreadBinaryTree() {DeleteBinaryTree(m_root);}
190 //    private:
191 //        T* m_root;
192 //}
193 
194 
195 }   // end of namespace binary_tree
196 #endif // end of _THREAD_BIANTY_TREE_H_
197 
//binary_search_tree.h
  1 #ifndef _BINARY_SEARCH_TREE_H_
  2 #define _BINARY_SEARCH_TREE_H_ 
  3 #include "binary_tree.h"
  4 namespace binary_tree{
  5 
  6 //当期二叉搜索树无重复值节点
  7 template<typename U, typename T = BinaryTreeNode<U> >
  8 class BinarySearchTree;
  9 
 10 // TODO 这个命名不太好
 11 // 允许有重复元素的二叉搜索树
 12 template<typename U, typename T = BinaryTreeNode<U> >
 13 class BinarySearchTree2;
 14 
 15 template<typename U>
 16 class BinarySearchTree< U, BinaryTreeNode<U> > : public BinaryTree< U, BinaryTreeNode<U> > {
 17     public:
 18         typedef BinaryTreeNode<U> T;
 19         // TODO why here do not need 构造函数,while BinaryTree need
 20         void InsertNode(const U elem) {
 21             //InsertNodeRec(this->m_root, elem);
 22             InsertNode(this->m_root, elem);
 23         }
 24         void DeleteNode(const U elem) {
 25             DeleteNode(this->m_root, elem);
 26         }
 27     private:
 28         void InsertNodeRec(T *&root,const U elem);
 29         virtual void InsertNode(T *root, const U elem);
 30         virtual void DeleteNode(T *root, const U elem);
 31         //void InsertNode(T *root, T *pn);
 32 };
 33 
 34 //允许相同的元素,后进入的相同元素插入到原元素右子树的最左下
 35 //well 这里有个问题,对于继承类,
 36 //例如 BinarySearchTre2<float> tree; tree.InserNode(3.0);  
 37 //编译器似乎只会找到 InsertNode(T *root, const U elem),认为它最匹配但不成功
 38 //而不会去基类中查找,解决办法避免重名重载?
 39 // TODO 这里先把虚函数名从 InsertNode改成InsertNode成功 不过感觉不爽
 40 // well 条款33,基类的名称被遮掩了!!所以编译器看不到基类的void InsertNode(const U elem)
 41 // 这个陷阱好深,其实编译器应该对子类的虚函数不要掩盖基类名称.
 42 // 另外编译器竟然还是要求virtual void DeleteNode(T *root, const U elem)
 43 // 提供定义,不能用基类默认的吗,哦,用默认的你就不要再写
 44 template<typename U>
 45 class BinarySearchTree2<U, BinaryTreeNode<U> > : public BinarySearchTree<U, BinaryTreeNode<U> > {
 46     public:
 47         typedef BinaryTreeNode<U> T;
 48         //这样也不行,因为基类有个virtual void InsertNode(T *root, const U elem);是私有
 49         //using  BinarySearchTree<U, BinaryTreeNode<U> >::InsertNode;
 50         //这能用转交函数了,或者你就改名 呵呵
 51         void InsertNode(const U elem) {
 52             BinarySearchTree<U, BinaryTreeNode<U> >::InsertNode(elem);
 53         }
 54         //递归函数打印min到mx之间的元素
 55         void PrintRange(T *root, U min, U max);
 56         int PrintRangeRec(T *root, U min, U max);
 57     private:
 58         virtual void InsertNode(T *root, const U elem);
 59         //virtual void DeleteNode(T *root, const U elem);
 60 };
 61 
 62 /*binary tree 实现*/
 63 
 64 //递归写法,简单,但是注意到每次只可能走一个分支,其实递归是没有意义的
 65 //可以很简单的写成非递归
 66 template <typename U>
 67 void BinarySearchTree< U,BinaryTreeNode<U> >::
 68 InsertNodeRec(BinaryTreeNode<U> *&root,const U elem) {
 69     typedef BinaryTreeNode<U> T;
 70     if (!root)
 71         root = new T(elem);
 72     else if (elem < root->elem())
 73         InsertNode(root->m_left, elem);
 74     else if (elem > root->elem())
 75         InsertNode(root->m_right, elem);
 76     else   //遇到相同节点,不需要插入
 77         return;
 78 }
 79 
 80 //So 不要递归思维定势
 81 template <typename U>
 82 void BinarySearchTree< U,BinaryTreeNode<U> >::
 83 InsertNode(BinaryTreeNode<U> *root,const U elem) {
 84     typedef BinaryTreeNode<U> T;
 85     //空树
 86     if (!root) {
 87         this->set_root(new T(elem));
 88         return;
 89     }
 90 
 91     T* p = root;
 92     
 93     while (1) {
 94         if (elem == p->elem())      //遇到相同的节点,无需插入了
 95            break
 96         if (elem < p->elem()) { 
 97             if (p ->left()) {
 98                 p = p->left();
 99             } else {
100                 p->set_left(new T(elem));
101                 break;
102             }
103 
104         } else {
105             if (p->right()) {
106                 p = p->right();
107             } else { 
108                 p->set_right(new T(elem));
109                 break;
110             }
111         }
112     }
113 }
114 template <typename U>
115 void BinarySearchTree< U,BinaryTreeNode<U> >::
116 DeleteNode(BinaryTreeNode<U> *root,const U elem) {
117     typedef BinaryTreeNode<U> T;
118     
119     if(this->IsEmpty())
120         return;
121      
122 }
123 
124 
125 /*带重复元素的binary tree实现*/
126 
127 template <typename U>
128 void BinarySearchTree2< U,BinaryTreeNode<U> >::
129 InsertNode(BinaryTreeNode<U> *root,const U elem) {
130     typedef BinaryTreeNode<U> T;
131     //空树
132     if (!root) {
133         this->set_root(new T(elem));
134         return;
135     }
136     T* p = root;
137     while (1) {
138         if (elem < p->elem()) { 
139             if (p ->left()) {
140                 p = p->left();
141             } else {
142                 p->set_left(new T(elem));
143                 break;
144             }
145 
146         } else {    // elem >= p->elem()
147             if (p->right()) {
148                 p = p->right();
149             } else { 
150                 p->set_right(new T(elem));
151                 break;
152             }
153         }
154     }
155 }
156 
157 template <typename U>
158 void BinarySearchTree2< U,BinaryTreeNode<U> >::
159 PrintRange(BinaryTreeNode<U> *root, U min, U max) {
160     assert(min <= max);
161     typedef BinaryTreeNode<U> T;
162     if (!root)
163         return;
164     if (root->elem() == min) {   //遇到了比min小或者相同的,其左子树无须访问了,相同需先访问根,小于则无需了直接右子树
165         Visit(root);
166         PrintRange(root->right(),min,max);
167     } else if (root->elem() > min) {    
168         PrintRange(root->left(),min,max);
169         if (root->elem() > max)  // 遇到更大的遍历结束
170             return;
171         Visit(root);
172         PrintRange(root->right(), root->elem(), max); //改成root->elem()没有太大优化
173     } else {
174         PrintRange(root->right(),min,max);
175     }
176 }
177 
178 template <typename U>
179 int BinarySearchTree2< U,BinaryTreeNode<U> >::
180 PrintRangeRec(BinaryTreeNode<U> *root, U min, U max) {
181     
182 }
183 
184 }        //end of namespace binary_tree
185 #endif   //end of _BINARY_SEARCH_TREE_H_ 
186 
原文地址:https://www.cnblogs.com/rocketfan/p/1556784.html