`
jgsj
  • 浏览: 956876 次
文章分类
社区版块
存档分类
最新评论

我强大的二叉树(先序、层序创建,先序、中序、后序、层序遍历)

阅读更多

要赶快些,要不然我们寝室就要断电了!
好了,经过四天的艰苦奋斗,我终于完成了一个比较强大的东西了。是什么东西呢?不是什么软件,不是什么程序,而是我自定义的一个数据结构!这个数据结构是二叉树。这个二叉树课不简单,因为它可以进行先序建立、层序建立,并且能够支持先序、中序、后序、层序的遍历。这个数据结构是我这四天来最有成果的一个了。因此我花费了超过24小时。想想自己在上课、吃饭、睡觉、上厕所都在想这个数据结构。能够有这个东西的横空出世,对我来说可真是可喜可贺啊。
今天晚上一直在研究层序创建二叉树的问题。昨天研究的是层序遍历二叉树的问题,因此我自己创建了一个链式队列(详见http://student.csdn.net/space.php?uid=999749&do=blog&id=48348)。有了这个队列,我就可以顺利地使用队列来进行层序遍历了。层序遍历的基本思想是:首先把根节点压入队尾,然后判断是否队列为空。如果为空,则退出循环。(当然没有出队的元素队伍是不会为空的)随后在循环体内进行出队操作,然后调用目标函数,再对左右孩子进行插入队尾的操作。如此循环,知道队列为空为之。这样的效果还真的不错。有了队列这个数据结构,我只需要几条语句就可以搞定层序遍历。
但是层序建立二叉树就没有那么简单了。其原因比较复杂,不好言传。但是今天晚上在我的努力下终于完成了。下面就是我为了编写这个功能而写的伪代码:

Code:
  1. 若根为空,则创建根节点。
  2. 将根节点进队,
  3. 如果队未空,则进入循环:
  4. {
  5. 删除队首元素,并取出来,
  6. 填充队首元素,
  7. 若左孩子满足条件,则创建左孩子,并且进队,
  8. 若右孩子满足条件,则创建右孩子,并且进队,
  9. }

说得简单,但是实现起来可是非常的困难的。我一遍又一遍地调试程序,到了现在,这个程序终于成功了。下面是我这个庞大二叉树的代码:

Code:
  1. /*-------------------------------------------
  2. 蒋轶民制作:E-mail:jiangcaiyang123@163.com
  3. ---------------------------------------------
  4. 文件名:JBiTree.h
  5. ---------------------------------------------
  6. 作用:这是一种二叉树的模板,它可以应用于任何
  7. 的需要二叉树的非线性结构的程序中。
  8. ---------------------------------------------
  9. 调用规范:①若将任意的类型运用于此,必须重载
  10. ==运算符,因为在判断两个数据类型的对象是否相
  11. 等的时候必须要用到它。②使用之前必须先定义类
  12. 型再包含该文件。例如:
  13. typedefstruct
  14. {
  15. chara
  16. intb;
  17. unsignedlongc;
  18. };
  19. #include"JBiTree.h"
  20. ③若用char类型进行实例化,那么给形参sizeofObj
  21. 传入的值必须减一。因为字符串是带'/0'的。
  22. ④具体函数的参数说明:
  23. voidSetImportData(CustomType*importObj,
  24. intsizeofObj,CustomTypedefaultObj);
  25. importObj:导入数据数组的首地址
  26. sizeofObj:数据数组的总大小,通常是sizeof(..)
  27. defaultObj:默认忽略建立树的结构数据
  28. boolCreateJBiTreeByPreOrder(JBiTreeNode
  29. <CustomType>*current);
  30. current:当前传入的数据节点,通常是GetRoot()
  31. 相同参数的函数:
  32. CreateJBiTreeByLevelOrder()
  33. voidPreOrderTraverse(
  34. JBiTreeNode<CustomType>*current,
  35. bool(*Visit)(CustomTypee));
  36. current:当前传入的数据节点,通常是GetRoot()
  37. Visit:具体的应用函数形参
  38. 相同参数的函数:
  39. InOrderTraverse()
  40. PostOrderTraverse()
  41. LevelOrderTraverse()
  42. ⑤在建立二叉树的时候,必须设置导入数据,不然会出错。// 更新于11月13日
  43. -------------------------------------------*/
  44. #ifndef_JBITREE_H_
  45. #define_JBITREE_H_
  46. #include"JChainQueue.h"
  47. //可将任何类型应用于此
  48. template<typenameCustomType>
  49. structJBiTreeNode//二叉树节点结构体(三叉节点)
  50. {
  51. JBiTreeNode():lchild(0),rchild(0){}
  52. CustomTypeelem;
  53. JBiTreeNode*lchild,*rchild;
  54. };//JBiTreeNode
  55. //可将任何类型应用于此
  56. template<typenameCustomType>
  57. classJBiTree//二叉树类
  58. {
  59. public:
  60. JBiTree():root(0),importData(0),startData(0),nodeCount(0){}//默认构造函数
  61. ~JBiTree(){}//默认析构函数
  62. voidSetImportData(CustomType*importObj,intsizeofObj,CustomTypedefaultObj);//设置导入的数据
  63. JBiTreeNode<CustomType>*GetRoot(void);//获取根节点
  64. boolCreateJBiTreeByPreOrder(JBiTreeNode<CustomType>*current);//先序创建二叉树
  65. boolCreateJBiTreeByLevelOrder(JBiTreeNode<CustomType>*current);//层序创建二叉树
  66. voidPreOrderTraverse(JBiTreeNode<CustomType>*current,bool(*Visit)(CustomTypee));//先序遍历二叉树
  67. voidInOrderTraverse(JBiTreeNode<CustomType>*current,bool(*Visit)(CustomTypee));//中序遍历二叉树
  68. voidPostOrderTraverse(JBiTreeNode<CustomType>*current,bool(*Visit)(CustomTypee));//后序遍历二叉树
  69. voidLevelOrderTraverse(JBiTreeNode<CustomType>*current,bool(*Visit)(CustomTypee));//层序遍历二叉树
  70. private:
  71. JBiTreeNode<CustomType>*root;
  72. CustomType*importData,*startData;
  73. CustomTypedefaultData;
  74. intnodeCount;
  75. };
  76. //设置导入的数据
  77. template<typenameCustomType>
  78. voidJBiTree<CustomType>::SetImportData(CustomTypeimportObj[],intsizeofObj,CustomTypedefaultObj)
  79. {
  80. startData=importData=importObj;
  81. nodeCount=sizeofObj/sizeof(CustomType);
  82. defaultData=defaultObj;
  83. }
  84. //获取根节点
  85. template<typenameCustomType>
  86. JBiTreeNode<CustomType>*JBiTree<CustomType>::GetRoot(void)
  87. {
  88. returnroot;
  89. }
  90. //层序创建二叉树
  91. template<typenameCustomType>
  92. boolJBiTree<CustomType>::CreateJBiTreeByLevelOrder(JBiTreeNode<CustomType>*current)
  93. {
  94. JChainQueue<JBiTreeNode<CustomType>*>temp;
  95. CustomType*dataTraverse=importData+1;//声明一个遍历的指针,从第二个元素开始
  96. if(importData==startData+nodeCount||*importData==defaultData)
  97. returnfalse;//若输入数据区为空且头结点为空则返回错误,因为不能创建树
  98. if(current==root)//若当前为根节点则创建根节点
  99. {
  100. root=newJBiTreeNode<CustomType>;
  101. current=root;
  102. }elsereturnfalse;
  103. temp.EnterQueue(current);
  104. while(!temp.IsEmpty())
  105. {
  106. current=temp.DeleteQueue();
  107. while(*importData==defaultData)
  108. importData++;
  109. current->elem=*importData;
  110. importData++;
  111. if(dataTraverse!=startData+nodeCount)
  112. {
  113. if(*dataTraverse!=defaultData)
  114. temp.EnterQueue(current->lchild=newJBiTreeNode<CustomType>);
  115. dataTraverse++;
  116. }
  117. if(dataTraverse!=startData+nodeCount)
  118. {
  119. if(*dataTraverse!=defaultData)
  120. temp.EnterQueue(current->rchild=newJBiTreeNode<CustomType>);
  121. dataTraverse++;
  122. }
  123. }
  124. returntrue;
  125. }
  126. //先序遍历二叉树
  127. template<typenameCustomType>
  128. voidJBiTree<CustomType>::PreOrderTraverse(JBiTreeNode<CustomType>*current,bool(*Visit)(CustomTypee))
  129. {
  130. if(current)
  131. {
  132. (*Visit)(current->elem);
  133. PreOrderTraverse(current->lchild,Visit);
  134. PreOrderTraverse(current->rchild,Visit);
  135. }
  136. }
  137. //中序遍历二叉树
  138. template<typenameCustomType>
  139. voidJBiTree<CustomType>::InOrderTraverse(JBiTreeNode<CustomType>*current,bool(*Visit)(CustomTypee))
  140. {
  141. if(current)
  142. {
  143. InOrderTraverse(current->lchild,Visit);
  144. (*Visit)(current->elem);
  145. InOrderTraverse(current->rchild,Visit);
  146. }
  147. }
  148. //后序遍历二叉树
  149. template<typenameCustomType>
  150. voidJBiTree<CustomType>::PostOrderTraverse(JBiTreeNode<CustomType>*current,bool(*Visit)(CustomTypee))
  151. {
  152. if(current)
  153. {
  154. PostOrderTraverse(current->lchild,Visit);
  155. PostOrderTraverse(current->rchild,Visit);
  156. (*Visit)(current->elem);
  157. }
  158. }
  159. //层序遍历二叉树
  160. template<typenameCustomType>
  161. voidJBiTree<CustomType>::LevelOrderTraverse(JBiTreeNode<CustomType>*current,bool(*Visit)(CustomTypee))
  162. {
  163. JChainQueue<JBiTreeNode<CustomType>*>temp;
  164. if(current==0)return;//当前节点为空则返回
  165. temp.EnterQueue(current);//将根节点入队列
  166. while(!temp.IsEmpty())
  167. {
  168. current=temp.DeleteQueue();
  169. (*Visit)(current->elem);
  170. if(current->lchild)temp.EnterQueue(current->lchild);
  171. if(current->rchild)temp.EnterQueue(current->rchild);
  172. }
  173. }
  174. //先序创建二叉树
  175. template<typenameCustomType>
  176. boolJBiTree<CustomType>::CreateJBiTreeByPreOrder(JBiTreeNode<CustomType>*current)
  177. {
  178. if(importData==startData+nodeCount||*importData==defaultData)
  179. returnfalse;//若输入数据区为空且头结点为空则返回错误,因为不能创建树
  180. if(current==root)//若当前为根节点则创建根节点
  181. {
  182. root=newJBiTreeNode<CustomType>;
  183. current=root;
  184. }
  185. current->elem=*importData;
  186. importData++;
  187. if(importData!=startData+nodeCount)
  188. {
  189. if(*importData!=defaultData)
  190. {
  191. current->lchild=newJBiTreeNode<CustomType>;
  192. CreateJBiTreeByPreOrder(current->lchild);
  193. }
  194. elseimportData++;
  195. }
  196. if(importData!=startData+nodeCount)
  197. {
  198. if(*importData!=defaultData)
  199. {
  200. current->rchild=newJBiTreeNode<CustomType>;
  201. CreateJBiTreeByPreOrder(current->rchild);
  202. }
  203. elseimportData++;
  204. }
  205. returntrue;
  206. }
  207. #endif

下面是我随便使用一个实例进行调用:

Code:
  1. #include<iostream>
  2. #include"JBiTree.h"
  3. usingnamespacestd;
  4. boolDisplay(chare)
  5. {
  6. cout<<e;
  7. returntrue;
  8. }
  9. intmain(intargc,char**argv)
  10. {
  11. JBiTree<char>jbtr;
  12. chardis[]="124___3579____68AC__D__B___";
  13. //chardis[]="1234_56";
  14. //chardis[]="1245____36__7_89___";
  15. jbtr.SetImportData(dis,sizeof(dis)-1,'_');
  16. //jbtr.CreateJBiTreeByLevelOrder(jbtr.GetRoot());
  17. jbtr.CreateJBiTreeByPreOrder(jbtr.GetRoot());
  18. jbtr.LevelOrderTraverse(jbtr.GetRoot(),Display);
  19. return0;
  20. }

二叉树很有用。因为在游戏开发中有些图像的索引是BSP树,而BSP树就是二叉树的一种。这次写的二叉树不仅仅是加深对二叉树的理解,而且是对我后续游戏的开发也是非常有帮助的。我希望自己强大的二叉树能够派上用场。

今天没有什么时间了,而且这个二叉树的模型还有诸多潜在的错误。希望大家能够将我的代码下载出来,并进行测试。并将错误反馈给我。我对大家的工作表示无尽的感谢。

更新于11月13日:大家难道没有发现吗?我的二叉树缺少了一个最重要的东西。销毁二叉树!如果不销毁的话,那么就会造成内存泄露这个重大的错误!这个东西我怎么会忘记呢!没办法,还是先这样吧。以后等我维护的时候再添加这个功能吧。现在先打记一下。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics