编程练习——伸展树(SplayTree)

伸展树用于查询结果的概率非平均情况,即起初假设某些要查询的信息偏多,有些信息几乎无人问津。对于平均访问概率来说,使用SplayTree实现并不是一个明智的选择。
可能会用到此数据结构的程序:词典或者多维搜索树,还有连接/切除树(link/cut tree)(这个树是用于网络优化问题包括最大流和最小代价)
  1. /*
  2. *createbychicochen
  3. *date:2008/10/02
  4. */
  5. template<classT>
  6. classSplayTree:publicBinaryTree<T>
  7. {
  8. public:
  9. explicitSplayTree(T&data):BinaryTree(data)
  10. {
  11. }
  12. explicitSplayTree(TreeNode<T>*root):BinaryTree(root)
  13. {
  14. }
  15. ~SplayTree()
  16. {
  17. }
  18. public:
  19. voidinsertNode(T&data)
  20. {
  21. if(NULL==this->head)
  22. {
  23. this->head=newTreeNode<T>(data);
  24. return;
  25. }
  26. splay(this->head,data);
  27. if(this->head->data>data)
  28. {
  29. //ABA
  30. // /\-> /\
  31. //CDCB
  32. //\
  33. //D
  34. TreeNode<T>*node=newTreeNode<T>(data);
  35. node->left=this->head->left;
  36. node->right=this->head;
  37. this->head->left=NULL;
  38. this->head=node;
  39. }
  40. elseif(this->head->data<data)
  41. {
  42. //ABA
  43. // /\-> /\
  44. //CDBD
  45. // /
  46. // C
  47. TreeNode<T>*node=newTreeNode<T>(data);
  48. node->right=this->head->right;
  49. node->left=this->head;
  50. this->head->right=NULL;
  51. this->head=node;
  52. }
  53. else
  54. {
  55. //insertthesamekey
  56. //throwexception
  57. throw"thesamekey";
  58. }
  59. }
  60. //usethedataaskeytosplaythetree
  61. //thenwecangetthestructuresofthetreelikethefollowing:
  62. //(1)A(2)A
  63. // \ /\
  64. // BCB
  65. //thedifferencebetweenthetwostructuresiswhethertheroothasleftchild
  66. //Incase(1),wecansimpliymaketherootrightchildinsteadtheroot.
  67. //Incase(2),weshouldsplaytherootleftsubtreeandthenitwillbe
  68. //changedlikecase(1),andwemakethesplayedleftsubtreerootinstead
  69. //theroot.
  70. voiddeleteNode(T&data)
  71. {
  72. if(NULL==this->head)
  73. {
  74. return;
  75. }
  76. splay(this->head,data);
  77. if(this->head->data!=data)
  78. {
  79. //notfoundthekeytodelete
  80. return;
  81. }
  82. TreeNode<T>*newRoot;
  83. if(NULL==this->head->left)
  84. {
  85. newRoot=this->head->right;
  86. }
  87. else
  88. {
  89. newRoot=this->head->left;
  90. splay(newRoot,data);
  91. newRoot->right=this->head->right;
  92. }
  93. deletethis->head;
  94. this->head=newRoot;
  95. }
  96. TreeNode<T>*searchNode(T&data)
  97. {
  98. if(NULL==this->head)
  99. {
  100. returnNULL;
  101. }
  102. splay(this->head,data);
  103. if(this->head->data==data)
  104. {
  105. returnthis->head;
  106. }
  107. returnNULL;
  108. }
  109. private:
  110. //usetop-downsplaymethod,
  111. //youshouldmakethesuitablefinalstep
  112. //accordingtothesituation,suchas"insert","delete","search".
  113. //Andwhat'sthetop-downmethod?
  114. //nowweshouldaddLeftMaxRootasLandRightMinRootasR
  115. //1.LAR2.LAR3.LAR
  116. // // /
  117. // BB B
  118. // /\
  119. //CC
  120. //
  121. //1.->LBR2.->LCR3.LCR
  122. //// \/
  123. //A B BA
  124. //\
  125. // A
  126. //butincase3.wecansimplifiedcase3rotateas
  127. //3.LBR
  128. // \ /
  129. // CA
  130. //andwemustintegratetheLeftMaxRootandRightMinRoottogether,
  131. //thenwehavefinalsteptodothis.AndLislefttree,andRisrighttree.
  132. //LARA
  133. ///\-> /\
  134. //BCLR
  135. // \/
  136. // BC
  137. voidsplay(TreeNode<T>*&subRoot,T&data)
  138. {
  139. if(NULL==subRoot)
  140. {
  141. return;
  142. }
  143. TreeNode<T>*leftRoot;
  144. TreeNode<T>*rightRoot;
  145. //heresomecodeusestaticmember,ifyoupromiseyouhavesync-control
  146. //oryoudon'tusethiscodeinthreadorprocess,youcouldchoosestatic
  147. //membertoaccelerateyourprogram.
  148. //Itmeansthefollowingcodeisthread-safe.
  149. TreeNode<T>head(data);
  150. leftRoot=rightRoot=&head;
  151. while(true)
  152. {
  153. if(data<subRoot->data)
  154. {
  155. if(NULL==subRoot->left)
  156. {
  157. break;
  158. }
  159. elseif(data<subRoot->left->data)
  160. {
  161. //Leftrotate
  162. TreeNode<T>*tempLeft=subRoot->left;
  163. subRoot->left=tempLeft->right;
  164. tempLeft->right=subRoot;
  165. subRoot=tempLeft;
  166. }
  167. else
  168. {
  169. //donothing
  170. }
  171. //splitthetreewithrightroot
  172. if(NULL==subRoot->left)
  173. break;
  174. rightRoot->left=subRoot;
  175. rightRoot=subRoot;
  176. subRoot=subRoot->left;
  177. }
  178. elseif(data>subRoot->data)
  179. {
  180. if(NULL==subRoot->right)
  181. {
  182. //neednottorotate
  183. break;
  184. }
  185. elseif(data>subRoot->right->data)
  186. {
  187. //rightrotate
  188. TreeNode<T>*tempRight=subRoot->right;
  189. subRoot->right=tempRight->left;
  190. tempRight->left=subRoot;
  191. subRoot=tempRight;
  192. }
  193. else
  194. {
  195. //donothing
  196. }
  197. //splitthetreebyleftroot
  198. if(NULL==subRoot->right)
  199. break;
  200. leftRoot->right=subRoot;
  201. leftRoot=subRoot;
  202. subRoot=subRoot->right;
  203. }
  204. else
  205. {
  206. //thesamekey
  207. break;
  208. }
  209. }
  210. //thefinalstep
  211. //wehavefindthelastnode,antthenweshould
  212. //integratetheleftroot,therightrootandtherootintoOnetree.
  213. //head.rightisleftroot
  214. //head.leftisrightroot
  215. leftRoot->right=subRoot->left;
  216. rightRoot->left=subRoot->right;
  217. subRoot->left=head.right;
  218. subRoot->right=head.left;
  219. }
  220. };

发现CSDN的代码编辑器还是有些问题,空格处理不好,导致我注释中的树形错乱了...

不过没有大关系,应该抓起旁边的纸边看边画就能明白。

在网上找splayTree的源码学习,发现凭自己的实力还真的看不懂.....

幸好在家里翻到了古老的数据结构教材。这才明白。

至于不使用添加父节点或者采用递归栈等方式的原因在于:空间消耗太大。

另外递归栈也不好调试

这个top-down splay的方法消耗空间为O(1),带来的效果却和添加父节点类似,没有使用递归的方法。

至于具体的方法,在代码的注释里。

这里为了编代码方便就没有将treeNode 类中的成员变量私有化。

另外的BinaryTree的代码在以前的blog中

这个splayTree还是较为完整的,至少比Apache中的splayTree完整些。现在我依旧不明白为什么Apache中的内存管理使用的是splayTree,而且splayTree还没有delete函数。难道内存管理的东西没有必要删除吗?

思考中....

你可能感兴趣的:(apache,数据结构,编程,Blog)