AVL,平衡二叉查找树。删除,插入,查找的复杂度都是O(logn)。它是一棵二叉树。对于每个节点来说,它的左孩子的键值都小于它,右孩子的键值都大于它。对于任意一个节点,它的左右孩子的高度差不大于1。树的高度的定义为:空节点的高度为0,非空节点的高度为左右孩子高度的最大值加1。

在插入删除过程中,会出现不平衡的时候。这时,会通过以下方式进行旋转保持树的平衡。下图中每一列最后一行是旋转后的结果,上面两行是对应的初始化状态。

1 插入。在以某个节点为根的子树中插入一个节点后,有可能使得该节点的左右子树的高度差大于1(其实此时的高度差是2),那么视情况进行LL,RR,LR,RL四种旋转中的一种可维持树的平衡。

2 删除。删除的键值小于当前节点键值时,在左子树中删除;大于当前节点键值时在右子树中进行删除;否则就是删除当前节点。删除当前节点时,找到后继节点,然后将后继结点替换当前节点,然后递归地删除这个后继结点即可。

  1. template<class _ValyeType,class _FuncType>
  2. class CAVLTree
  3. {
  4. protected:
  5. struct AVLTreeNode
  6. {
  7. _ValyeType m_iValue;
  8. AVLTreeNode* m_pLeftSon;
  9. AVLTreeNode* m_pRightSon;
  10. int m_nHeight;
  11. int m_nValueNumber;
  12. };
  13. AVLTreeNode* m_pRoot;
  14. _FuncType* m_pCompareFunc;
  15.  
  16. AVLTreeNode* _NewNode()
  17. {
  18. AVLTreeNode* pNode=new AVLTreeNode;
  19. pNode->m_pLeftSon=nullptr;
  20. pNode->m_pRightSon=nullptr;
  21. pNode->m_nHeight=;
  22. pNode->m_nValueNumber=;
  23. return pNode;
  24. }
  25. AVLTreeNode* _NewNode(const _ValyeType& iValue)
  26. {
  27. AVLTreeNode* pNode=new AVLTreeNode;
  28. pNode->m_pLeftSon=nullptr;
  29. pNode->m_pRightSon=nullptr;
  30. pNode->m_nHeight=;
  31. pNode->m_iValue=iValue;
  32. pNode->m_nValueNumber=;
  33. return pNode;
  34. }
  35.  
  36. int _Height(AVLTreeNode* pNode)
  37. {
  38. if(pNode) return pNode->m_nHeight;
  39. return ;
  40. }
  41.  
  42. void _PushUp(AVLTreeNode* pNode)
  43. {
  44. if(!pNode) return;
  45. const int nLeftSonHeight=_Height(pNode->m_pLeftSon);
  46. const int nRightSonHeight=_Height(pNode->m_pRightSon);
  47. if(nLeftSonHeight<nRightSonHeight) pNode->m_nHeight=+nRightSonHeight;
  48. else pNode->m_nHeight=+nLeftSonHeight;
  49. }
  50.  
  51. /**
  52. pNode的左孩子将成为根,返回新的树根
  53. **/
  54. AVLTreeNode* _LLRotate(AVLTreeNode* pNode)
  55. {
  56. if(!pNode) return pNode;
  57. AVLTreeNode* pLeftSon=pNode->m_pLeftSon;
  58. pNode->m_pLeftSon=pLeftSon->m_pRightSon;
  59. pLeftSon->m_pRightSon=pNode;
  60. _PushUp(pNode);
  61. _PushUp(pLeftSon);
  62. return pLeftSon;
  63. }
  64.  
  65. /**
  66. pNode的右孩子将成为根,返回新的树根
  67. **/
  68. AVLTreeNode* _RRRotate(AVLTreeNode* pNode)
  69. {
  70. if(!pNode) return pNode;
  71. AVLTreeNode* pRightSon=pNode->m_pRightSon;
  72. pNode->m_pRightSon=pRightSon->m_pLeftSon;
  73. pRightSon->m_pLeftSon=pNode;
  74. _PushUp(pNode);
  75. _PushUp(pRightSon);
  76. return pRightSon;
  77. }
  78. /**
  79. pNode的左孩子的右孩子将成为根,返回新的树根
  80. **/
  81. AVLTreeNode* _LRRotate(AVLTreeNode* pNode)
  82. {
  83. if(!pNode) return pNode;
  84. pNode->m_pLeftSon=_RRRotate(pNode->m_pLeftSon);
  85. return _LLRotate(pNode);
  86. }
  87.  
  88. /**
  89. pNode的右孩子的左孩子将成为根,返回新的树根
  90. **/
  91. AVLTreeNode* _RLRotate(AVLTreeNode* pNode)
  92. {
  93. if(!pNode) return pNode;
  94. pNode->m_pRightSon=_LLRotate(pNode->m_pRightSon);
  95. return _RRRotate(pNode);
  96. }
  97.  
  98. AVLTreeNode* _Rotate(AVLTreeNode* pNode)
  99. {
  100. if(!pNode) return pNode;
  101. if(==_Height(pNode->m_pLeftSon)-_Height(pNode->m_pRightSon))
  102. {
  103. if(_Height(pNode->m_pLeftSon->m_pLeftSon)>=_Height(pNode->m_pLeftSon->m_pRightSon))
  104. {
  105. pNode=_LLRotate(pNode);
  106. }
  107. else pNode=_LRRotate(pNode);
  108. }
  109. else if(==_Height(pNode->m_pRightSon)-_Height(pNode->m_pLeftSon))
  110. {
  111. if(_Height(pNode->m_pRightSon->m_pLeftSon)>=_Height(pNode->m_pRightSon->m_pRightSon))
  112. {
  113. pNode=_RLRotate(pNode);
  114. }
  115. else pNode=_RRRotate(pNode);
  116. }
  117. return pNode;
  118. }
  119.  
  120. AVLTreeNode* _Insert(AVLTreeNode* pRoot,const _ValyeType& iInsertValue)
  121. {
  122. if(nullptr==pRoot)
  123. {
  124. pRoot=_NewNode(iInsertValue); return pRoot;
  125. }
  126. else if(m_pCompareFunc(iInsertValue,pRoot->m_iValue))
  127. {
  128. pRoot->m_pLeftSon=_Insert(pRoot->m_pLeftSon,iInsertValue);
  129. if(==_Height(pRoot->m_pLeftSon)-_Height(pRoot->m_pRightSon))
  130. {
  131. if(m_pCompareFunc(iInsertValue,pRoot->m_pLeftSon->m_iValue))
  132. {
  133. pRoot=_LLRotate(pRoot);
  134. }
  135. else
  136. {
  137. pRoot=_LRRotate(pRoot);
  138. }
  139. }
  140. }
  141. else if(m_pCompareFunc(pRoot->m_iValue,iInsertValue))
  142. {
  143. pRoot->m_pRightSon=_Insert(pRoot->m_pRightSon,iInsertValue);
  144. if(==_Height(pRoot->m_pRightSon)-_Height(pRoot->m_pLeftSon))
  145. {
  146. if(m_pCompareFunc(iInsertValue,pRoot->m_pRightSon->m_iValue))
  147. {
  148. pRoot=_RLRotate(pRoot);
  149. }
  150. else
  151. {
  152. pRoot=_RRRotate(pRoot);
  153. }
  154. }
  155. }
  156. else
  157. {
  158. ++pRoot->m_nValueNumber;
  159. }
  160.  
  161. _PushUp(pRoot);
  162. return pRoot;
  163. }
  164.  
  165. AVLTreeNode* _Delete(AVLTreeNode* pRoot,const _ValyeType& iDeleteValue)
  166. {
  167. if(nullptr==pRoot) return nullptr;
  168. if(m_pCompareFunc(iDeleteValue,pRoot->m_iValue))
  169. {
  170. pRoot->m_pLeftSon=_Delete(pRoot->m_pLeftSon,iDeleteValue);
  171. }
  172. else if(m_pCompareFunc(pRoot->m_iValue,iDeleteValue))
  173. {
  174. pRoot->m_pRightSon=_Delete(pRoot->m_pRightSon,iDeleteValue);
  175. }
  176. else
  177. {
  178. if(==--pRoot->m_nValueNumber)
  179. {
  180. if(nullptr==pRoot->m_pLeftSon)
  181. {
  182. AVLTreeNode* pTmp=pRoot;
  183. pRoot=pRoot->m_pRightSon;
  184. delete pTmp;
  185. }
  186. else if(nullptr==pRoot->m_pRightSon)
  187. {
  188. AVLTreeNode* pTmp=pRoot;
  189. pRoot=pRoot->m_pLeftSon;
  190. delete pTmp;
  191. }
  192. else
  193. {
  194. AVLTreeNode* pTmp=pRoot->m_pRightSon;
  195. while(pTmp->m_pLeftSon) pTmp=pTmp->m_pLeftSon;
  196. pRoot->m_iValue=pTmp->m_iValue;
  197. pRoot->m_pRightSon=_Delete(pRoot->m_pRightSon,pRoot->m_iValue);
  198. }
  199. }
  200. else
  201. {
  202. return pRoot;
  203. }
  204. }
  205. _PushUp(pRoot);
  206. if(pRoot&&pRoot->m_pLeftSon) pRoot->m_pLeftSon=_Rotate(pRoot->m_pLeftSon);
  207. if(pRoot&&pRoot->m_pRightSon) pRoot->m_pRightSon=_Rotate(pRoot->m_pRightSon);
  208. if(pRoot) pRoot=_Rotate(pRoot);
  209. return pRoot;
  210. }
  211.  
  212. public:
  213. CAVLTree(_FuncType* pCompareFunc):m_pRoot(nullptr),m_pCompareFunc(pCompareFunc) {}
  214.  
  215. void Insert(const _ValyeType& iInsertValue)
  216. {
  217. m_pRoot=_Insert(m_pRoot,iInsertValue);
  218. }
  219.  
  220. void Delete(const _ValyeType& iDeleteValue)
  221. {
  222. m_pRoot=_Delete(m_pRoot,iDeleteValue);
  223. }
  224.  
  225. int Find(const _ValyeType& iSearchValue)
  226. {
  227. AVLTreeNode* pCurrent=m_pRoot;
  228. while()
  229. {
  230. if(!pCurrent) break;
  231. if(m_pCompareFunc(iSearchValue,pCurrent->m_iValue))
  232. {
  233. pCurrent=pCurrent->m_pLeftSon;
  234. }
  235. else if(m_pCompareFunc(pCurrent->m_iValue,iSearchValue))
  236. {
  237. pCurrent=pCurrent->m_pRightSon;
  238. }
  239. else return pCurrent->m_nValueNumber;
  240. }
  241. return ;
  242. }
  243.  
  244. };

AVL学习笔记的更多相关文章

  1. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

  2. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  3. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  4. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  5. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  6. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  7. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  8. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  9. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

随机推荐

  1. C# 控制台程序如何防止启动多个实例

    ==================================================================================================== ...

  2. PDO讲解

    PDO的知识点标注在代码里 <?php //造DSN:驱动名:dbname=数据库名:host=服务器地址 $dsn="mysql:dbname=mydb;host=localhost ...

  3. cf-282e

    “字典树”的变形,任意两数异或最大值,处理字典树的时候可以用递归,也可以用循环,下面有两个版本. C - Sausage Maximization Time Limit:2000MS Memory L ...

  4. javascript加载顺序

    javascript加载顺序 <script type="text/javascript" src="jquery.js"></script& ...

  5. 初学android的第一个习作

    首发:个人博客,更新&纠错&回复 项目源码在这里,因为github上传速度太差,传到了oschina的git托管上. 1.项目结构及技术点 主页面使用FragmentTabHost,5 ...

  6. android 项目学习随笔二(引导页 )

    1.引导页 1.定义灰色.红色圆点的shape XML文件 2.定义布局文件,利用相对布局文件定位,利用线性布局加载灰色圆点,imageview加载红色圆点 3.android.support.v4. ...

  7. 鸟哥的linux私房菜之vim

    vim是vi的进阶版本

  8. Bootstrap之Carousel问题

    一.不能自动播放的解决办法 1.默认使用Bootstrap的Carousel组件,只需要加上 data-ride="carousel" 就可以实现自动播放了.无需使用初始化的js函 ...

  9. 160907、CSS 预处理器-Less

    CSS 预处理器是什么?一般来说,它们基于 CSS 扩展了一套属于自己的 DSL,来解决我们书写 CSS 时难以解决的问题: 语法不够强大,比如无法嵌套书写导致模块化开发中需要书写很多重复的选择器: ...

  10. Linux按键驱动程序设计详解---从简单到不简单【转】

    转自:http://blog.csdn.net/coding__madman/article/details/51399353 版权声明:本文为博主原创文章,未经博主允许不得转载. 混杂设备驱动模型: ...