第五十八课 树形结构的层次遍历
Posted wanmeishenghuo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第五十八课 树形结构的层次遍历相关的知识,希望对你有一定的参考价值。
通用树结构是一种容器,里面装有数据元素,我们有遍历元素的需求。
非线性决定了树中的每个结点没有固定的编号方式。
将队列中队首的指针定义成遍历时的游标,根节点进入队列后,游标指向根节点。
队头元素弹出,队首的指针就指向了别的元素,这就相当于移动了游标。
添加遍历相关的程序:
1 #ifndef GTREE_H 2 #define GTREE_H 3 4 #include "Tree.h" 5 #include "GTreeNode.h" 6 #include "Exception.h" 7 #include "LinkQueue.h" 8 9 namespace DTLib 10 { 11 12 template < typename T > 13 class GTree : public Tree<T> 14 { 15 protected: 16 LinkQueue<GTreeNode<T>*> m_queue; 17 18 GTree(const GTree<T>&); 19 GTree<T>& operator = (const GTree<T>&); 20 21 GTreeNode<T>* find(GTreeNode<T>* node, const T& value) const 22 { 23 GTreeNode<T>* ret = NULL; 24 25 if( node != NULL ) 26 { 27 if( node->value == value ) 28 { 29 return node; 30 } 31 else 32 { 33 for(node->child.move(0); !node->child.end() && (ret == NULL); node->child.next()) 34 { 35 ret = find(node->child.current(), value); 36 } 37 } 38 } 39 40 return ret; 41 } 42 43 GTreeNode<T>* find(GTreeNode<T>* node, GTreeNode<T>* obj) const 44 { 45 GTreeNode<T>* ret = NULL; 46 47 if( node == obj ) 48 { 49 return node; 50 } 51 else 52 { 53 if( node != NULL ) 54 { 55 for( node->child.move(0); !node->child.end() && (ret == NULL); node->child.next()) 56 { 57 ret = find(node->child.current(), obj); 58 } 59 } 60 } 61 62 return ret; 63 } 64 65 void free(GTreeNode<T>* node) 66 { 67 if( node != NULL ) 68 { 69 for(node->child.move(0); !node->child.end(); node->child.next()) 70 { 71 free(node->child.current()); 72 } 73 74 if( node->flag() ) 75 { 76 delete node; 77 } 78 } 79 } 80 81 void remove(GTreeNode<T>* node, GTree<T>*& ret) 82 { 83 ret = new GTree<T>(); 84 85 if( ret == NULL ) 86 { 87 THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create tree..."); 88 } 89 else 90 { 91 if( root() == node ) 92 { 93 this->m_root = NULL; 94 } 95 else 96 { 97 LinkList<GTreeNode<T>*>& child = dynamic_cast<GTreeNode<T>*>(node->parent)->child; 98 99 child.remove(child.find(node)); 100 101 node->parent = NULL; 102 } 103 104 ret->m_root = node; 105 } 106 } 107 108 int count(GTreeNode<T>* node) const 109 { 110 int ret = 0; 111 112 if( node != NULL ) 113 { 114 ret = 1; 115 116 //node如果没有孩子,则for不执行 117 for(node->child.move(0); !node->child.end(); node->child.next()) 118 { 119 ret += count(node->child.current()); 120 } 121 } 122 123 return ret; 124 } 125 126 int height(GTreeNode<T>* node) const 127 { 128 int ret = 0; 129 130 if( node != NULL ) 131 { 132 for(node->child.move(0); !node->child.end(); node->child.next()) 133 { 134 int h = height(node->child.current()); 135 136 if( ret < h ) 137 { 138 ret = h; 139 } 140 } 141 142 ret = ret + 1; 143 } 144 145 return ret; 146 } 147 148 int degree(GTreeNode<T>* node) const 149 { 150 int ret = 0; 151 152 if( node != NULL ) 153 { 154 ret = node->child.length(); //根节点的度数 155 156 for(node->child.move(0); !node->child.end(); node->child.next()) 157 { 158 int d = degree(node->child.current()); 159 160 if( ret < d ) 161 { 162 ret = d; 163 } 164 } 165 } 166 167 return ret; 168 } 169 public: 170 GTree() 171 { 172 173 } 174 bool insert(TreeNode<T>* node) 175 { 176 bool ret = true; 177 178 if( node != NULL ) 179 { 180 if( this->m_root == NULL ) //如果待插入节点的父节点为空,则这个节点将为根节点 181 { 182 node->parent = NULL; 183 this->m_root = node; 184 } 185 else 186 { 187 GTreeNode<T>* np = find(node->parent); 188 189 if( np != NULL ) 190 { 191 GTreeNode<T>* n = dynamic_cast<GTreeNode<T>*>(node); 192 193 if( np->child.find(n) < 0 ) 194 { 195 np->child.insert(n); 196 } 197 } 198 else 199 { 200 THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node..."); 201 } 202 } 203 } 204 else 205 { 206 THROW_EXCEPTION(InvalidParameterException, "Parameter node cannot be NULL ..."); 207 } 208 209 return ret; 210 } 211 212 bool insert(const T& value, TreeNode<T>* parent) 213 { 214 bool ret = true; 215 216 GTreeNode<T>* node = GTreeNode<T>::NewNode(); 217 218 if( node != NULL ) 219 { 220 node->value = value; 221 node->parent = parent; 222 223 insert(node); 224 } 225 else 226 { 227 THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ..."); 228 } 229 230 return ret; 231 } 232 233 //删除的节点的子节点我们还需要处理,因此要返回删除节点的指针,这样有机会对里面的元素做进一步操作 234 SharedPointer< Tree<T> > remove(const T& value) 235 { 236 GTree<T>* ret = NULL; 237 238 GTreeNode<T>* node = find(value); 239 240 if( node == NULL ) 241 { 242 THROW_EXCEPTION(InvalidParameterException, "can not find the node ..."); 243 } 244 else 245 { 246 remove(node, ret); 247 248 m_queue.clear(); 249 } 250 251 return ret; 252 } 253 254 SharedPointer< Tree<T> > remove(TreeNode<T>* node) 255 { 256 GTree<T>* ret = NULL; 257 258 node = find(node); 259 260 if( node == NULL ) 261 { 262 THROW_EXCEPTION(InvalidParameterException, "parameter node is invalid ..."); 263 } 264 else 265 { 266 remove(dynamic_cast<GTreeNode<T>*>(node), ret); 267 268 m_queue.clear(); 269 } 270 271 return ret; 272 } 273 274 GTreeNode<T>* find(const T& value) const // 返回GTreeNode,赋值兼容性 275 { 276 return find(root(), value); 277 } 278 279 GTreeNode<T>* find(TreeNode<T>* node) const 280 { 281 return find(root(), dynamic_cast<GTreeNode<T>*>(node)); 282 } 283 284 GTreeNode<T>* root() const 285 { 286 return dynamic_cast<GTreeNode<T>*>(this->m_root); 287 } 288 289 int degree() const 290 { 291 return degree(root()); 292 } 293 int count() const 294 { 295 return count(root()); 296 } 297 298 int height() const 299 { 300 return height(root()); 301 } 302 303 void clear() 304 { 305 free(root()); 306 307 this->m_root = NULL; 308 309 m_queue.clear(); 310 } 311 312 bool begin() 313 { 314 bool ret = ( root() != NULL ); 315 316 if( ret ) 317 { 318 m_queue.clear(); 319 m_queue.add(root()); 320 } 321 322 return ret; 323 } 324 325 bool end() 326 { 327 return (m_queue.length() == 0); 328 } 329 330 bool next() 331 { 332 bool ret = (m_queue.length() > 0); 333 334 if( ret ) 335 { 336 GTreeNode<T>* node = m_queue.front(); 337 338 m_queue.remove(); //将对头元素出队,相当于移动游标 339 340 for(node->child.move(0); !node->child.end(); node->child.next()) 341 { 342 m_queue.add(node->child.current()); 343 } 344 } 345 346 return ret; 347 } 348 349 T current() 350 { 351 if( !end() ) //遍历的过程当中调用current函数才有意义 352 { 353 return m_queue.front()->value; 354 } 355 else 356 { 357 THROW_EXCEPTION(InvalidOperationException, "No value at current position..."); 358 } 359 } 360 361 ~GTree() 362 { 363 clear(); 364 } 365 }; 366 367 } 368 369 #endif // GTREE_H
测试程序如下:
1 #include <iostream> 2 #include "GTree.h" 3 #include "GTreeNode.h" 4 5 6 using namespace std; 7 using namespace DTLib; 8 9 10 int main() 11 { 12 GTree<char> t; 13 GTreeNode<char>* node = NULL; 14 GTreeNode<char> root; 15 16 root.value = ‘A‘; 17 root.parent = NULL; 18 19 t.insert(&root); 20 21 node = t.find(‘A‘); 22 t.insert(‘B‘, node); 23 t.insert(‘C‘, node); 24 t.insert(‘D‘, node); 25 26 node = t.find(‘B‘); 27 t.insert(‘E‘, node); 28 t.insert(‘F‘, node); 29 30 node = t.find(‘E‘); 31 t.insert(‘K‘, node); 32 t.insert(‘L‘, node); 33 34 node = t.find(‘C‘); 35 t.insert(‘G‘, node); 36 37 node = t.find(‘D‘); 38 t.insert(‘H‘, node); 39 t.insert(‘I‘, node); 40 t.insert(‘J‘, node); 41 42 node = t.find(‘H‘); 43 t.insert(‘M‘, node); 44 45 cout << t.degree() << endl; 46 47 for(t.begin(); !t.end(); t.next()) 48 { 49 cout << t.current() << endl; 50 } 51 52 return 0; 53 }
结果如下:
小结:
以上是关于第五十八课 树形结构的层次遍历的主要内容,如果未能解决你的问题,请参考以下文章