AVL学习笔记
AVL,平衡二叉查找树。删除,插入,查找的复杂度都是O(logn)。它是一棵二叉树。对于每个节点来说,它的左孩子的键值都小于它,右孩子的键值都大于它。对于任意一个节点,它的左右孩子的高度差不大于1。树的高度的定义为:空节点的高度为0,非空节点的高度为左右孩子高度的最大值加1。
在插入删除过程中,会出现不平衡的时候。这时,会通过以下方式进行旋转保持树的平衡。下图中每一列最后一行是旋转后的结果,上面两行是对应的初始化状态。
1 插入。在以某个节点为根的子树中插入一个节点后,有可能使得该节点的左右子树的高度差大于1(其实此时的高度差是2),那么视情况进行LL,RR,LR,RL四种旋转中的一种可维持树的平衡。
2 删除。删除的键值小于当前节点键值时,在左子树中删除;大于当前节点键值时在右子树中进行删除;否则就是删除当前节点。删除当前节点时,找到后继节点,然后将后继结点替换当前节点,然后递归地删除这个后继结点即可。
- template<class _ValyeType,class _FuncType>
- class CAVLTree
- {
- protected:
- struct AVLTreeNode
- {
- _ValyeType m_iValue;
- AVLTreeNode* m_pLeftSon;
- AVLTreeNode* m_pRightSon;
- int m_nHeight;
- int m_nValueNumber;
- };
- AVLTreeNode* m_pRoot;
- _FuncType* m_pCompareFunc;
- AVLTreeNode* _NewNode()
- {
- AVLTreeNode* pNode=new AVLTreeNode;
- pNode->m_pLeftSon=nullptr;
- pNode->m_pRightSon=nullptr;
- pNode->m_nHeight=;
- pNode->m_nValueNumber=;
- return pNode;
- }
- AVLTreeNode* _NewNode(const _ValyeType& iValue)
- {
- AVLTreeNode* pNode=new AVLTreeNode;
- pNode->m_pLeftSon=nullptr;
- pNode->m_pRightSon=nullptr;
- pNode->m_nHeight=;
- pNode->m_iValue=iValue;
- pNode->m_nValueNumber=;
- return pNode;
- }
- int _Height(AVLTreeNode* pNode)
- {
- if(pNode) return pNode->m_nHeight;
- return ;
- }
- void _PushUp(AVLTreeNode* pNode)
- {
- if(!pNode) return;
- const int nLeftSonHeight=_Height(pNode->m_pLeftSon);
- const int nRightSonHeight=_Height(pNode->m_pRightSon);
- if(nLeftSonHeight<nRightSonHeight) pNode->m_nHeight=+nRightSonHeight;
- else pNode->m_nHeight=+nLeftSonHeight;
- }
- /**
- pNode的左孩子将成为根,返回新的树根
- **/
- AVLTreeNode* _LLRotate(AVLTreeNode* pNode)
- {
- if(!pNode) return pNode;
- AVLTreeNode* pLeftSon=pNode->m_pLeftSon;
- pNode->m_pLeftSon=pLeftSon->m_pRightSon;
- pLeftSon->m_pRightSon=pNode;
- _PushUp(pNode);
- _PushUp(pLeftSon);
- return pLeftSon;
- }
- /**
- pNode的右孩子将成为根,返回新的树根
- **/
- AVLTreeNode* _RRRotate(AVLTreeNode* pNode)
- {
- if(!pNode) return pNode;
- AVLTreeNode* pRightSon=pNode->m_pRightSon;
- pNode->m_pRightSon=pRightSon->m_pLeftSon;
- pRightSon->m_pLeftSon=pNode;
- _PushUp(pNode);
- _PushUp(pRightSon);
- return pRightSon;
- }
- /**
- pNode的左孩子的右孩子将成为根,返回新的树根
- **/
- AVLTreeNode* _LRRotate(AVLTreeNode* pNode)
- {
- if(!pNode) return pNode;
- pNode->m_pLeftSon=_RRRotate(pNode->m_pLeftSon);
- return _LLRotate(pNode);
- }
- /**
- pNode的右孩子的左孩子将成为根,返回新的树根
- **/
- AVLTreeNode* _RLRotate(AVLTreeNode* pNode)
- {
- if(!pNode) return pNode;
- pNode->m_pRightSon=_LLRotate(pNode->m_pRightSon);
- return _RRRotate(pNode);
- }
- AVLTreeNode* _Rotate(AVLTreeNode* pNode)
- {
- if(!pNode) return pNode;
- if(==_Height(pNode->m_pLeftSon)-_Height(pNode->m_pRightSon))
- {
- if(_Height(pNode->m_pLeftSon->m_pLeftSon)>=_Height(pNode->m_pLeftSon->m_pRightSon))
- {
- pNode=_LLRotate(pNode);
- }
- else pNode=_LRRotate(pNode);
- }
- else if(==_Height(pNode->m_pRightSon)-_Height(pNode->m_pLeftSon))
- {
- if(_Height(pNode->m_pRightSon->m_pLeftSon)>=_Height(pNode->m_pRightSon->m_pRightSon))
- {
- pNode=_RLRotate(pNode);
- }
- else pNode=_RRRotate(pNode);
- }
- return pNode;
- }
- AVLTreeNode* _Insert(AVLTreeNode* pRoot,const _ValyeType& iInsertValue)
- {
- if(nullptr==pRoot)
- {
- pRoot=_NewNode(iInsertValue); return pRoot;
- }
- else if(m_pCompareFunc(iInsertValue,pRoot->m_iValue))
- {
- pRoot->m_pLeftSon=_Insert(pRoot->m_pLeftSon,iInsertValue);
- if(==_Height(pRoot->m_pLeftSon)-_Height(pRoot->m_pRightSon))
- {
- if(m_pCompareFunc(iInsertValue,pRoot->m_pLeftSon->m_iValue))
- {
- pRoot=_LLRotate(pRoot);
- }
- else
- {
- pRoot=_LRRotate(pRoot);
- }
- }
- }
- else if(m_pCompareFunc(pRoot->m_iValue,iInsertValue))
- {
- pRoot->m_pRightSon=_Insert(pRoot->m_pRightSon,iInsertValue);
- if(==_Height(pRoot->m_pRightSon)-_Height(pRoot->m_pLeftSon))
- {
- if(m_pCompareFunc(iInsertValue,pRoot->m_pRightSon->m_iValue))
- {
- pRoot=_RLRotate(pRoot);
- }
- else
- {
- pRoot=_RRRotate(pRoot);
- }
- }
- }
- else
- {
- ++pRoot->m_nValueNumber;
- }
- _PushUp(pRoot);
- return pRoot;
- }
- AVLTreeNode* _Delete(AVLTreeNode* pRoot,const _ValyeType& iDeleteValue)
- {
- if(nullptr==pRoot) return nullptr;
- if(m_pCompareFunc(iDeleteValue,pRoot->m_iValue))
- {
- pRoot->m_pLeftSon=_Delete(pRoot->m_pLeftSon,iDeleteValue);
- }
- else if(m_pCompareFunc(pRoot->m_iValue,iDeleteValue))
- {
- pRoot->m_pRightSon=_Delete(pRoot->m_pRightSon,iDeleteValue);
- }
- else
- {
- if(==--pRoot->m_nValueNumber)
- {
- if(nullptr==pRoot->m_pLeftSon)
- {
- AVLTreeNode* pTmp=pRoot;
- pRoot=pRoot->m_pRightSon;
- delete pTmp;
- }
- else if(nullptr==pRoot->m_pRightSon)
- {
- AVLTreeNode* pTmp=pRoot;
- pRoot=pRoot->m_pLeftSon;
- delete pTmp;
- }
- else
- {
- AVLTreeNode* pTmp=pRoot->m_pRightSon;
- while(pTmp->m_pLeftSon) pTmp=pTmp->m_pLeftSon;
- pRoot->m_iValue=pTmp->m_iValue;
- pRoot->m_pRightSon=_Delete(pRoot->m_pRightSon,pRoot->m_iValue);
- }
- }
- else
- {
- return pRoot;
- }
- }
- _PushUp(pRoot);
- if(pRoot&&pRoot->m_pLeftSon) pRoot->m_pLeftSon=_Rotate(pRoot->m_pLeftSon);
- if(pRoot&&pRoot->m_pRightSon) pRoot->m_pRightSon=_Rotate(pRoot->m_pRightSon);
- if(pRoot) pRoot=_Rotate(pRoot);
- return pRoot;
- }
- public:
- CAVLTree(_FuncType* pCompareFunc):m_pRoot(nullptr),m_pCompareFunc(pCompareFunc) {}
- void Insert(const _ValyeType& iInsertValue)
- {
- m_pRoot=_Insert(m_pRoot,iInsertValue);
- }
- void Delete(const _ValyeType& iDeleteValue)
- {
- m_pRoot=_Delete(m_pRoot,iDeleteValue);
- }
- int Find(const _ValyeType& iSearchValue)
- {
- AVLTreeNode* pCurrent=m_pRoot;
- while()
- {
- if(!pCurrent) break;
- if(m_pCompareFunc(iSearchValue,pCurrent->m_iValue))
- {
- pCurrent=pCurrent->m_pLeftSon;
- }
- else if(m_pCompareFunc(pCurrent->m_iValue,iSearchValue))
- {
- pCurrent=pCurrent->m_pRightSon;
- }
- else return pCurrent->m_nValueNumber;
- }
- return ;
- }
- };
AVL学习笔记的更多相关文章
- 尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- CSS学习笔记
CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...
- HTML学习笔记
HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...
随机推荐
- C# 控制台程序如何防止启动多个实例
==================================================================================================== ...
- PDO讲解
PDO的知识点标注在代码里 <?php //造DSN:驱动名:dbname=数据库名:host=服务器地址 $dsn="mysql:dbname=mydb;host=localhost ...
- cf-282e
“字典树”的变形,任意两数异或最大值,处理字典树的时候可以用递归,也可以用循环,下面有两个版本. C - Sausage Maximization Time Limit:2000MS Memory L ...
- javascript加载顺序
javascript加载顺序 <script type="text/javascript" src="jquery.js"></script& ...
- 初学android的第一个习作
首发:个人博客,更新&纠错&回复 项目源码在这里,因为github上传速度太差,传到了oschina的git托管上. 1.项目结构及技术点 主页面使用FragmentTabHost,5 ...
- android 项目学习随笔二(引导页 )
1.引导页 1.定义灰色.红色圆点的shape XML文件 2.定义布局文件,利用相对布局文件定位,利用线性布局加载灰色圆点,imageview加载红色圆点 3.android.support.v4. ...
- 鸟哥的linux私房菜之vim
vim是vi的进阶版本
- Bootstrap之Carousel问题
一.不能自动播放的解决办法 1.默认使用Bootstrap的Carousel组件,只需要加上 data-ride="carousel" 就可以实现自动播放了.无需使用初始化的js函 ...
- 160907、CSS 预处理器-Less
CSS 预处理器是什么?一般来说,它们基于 CSS 扩展了一套属于自己的 DSL,来解决我们书写 CSS 时难以解决的问题: 语法不够强大,比如无法嵌套书写导致模块化开发中需要书写很多重复的选择器: ...
- Linux按键驱动程序设计详解---从简单到不简单【转】
转自:http://blog.csdn.net/coding__madman/article/details/51399353 版权声明:本文为博主原创文章,未经博主允许不得转载. 混杂设备驱动模型: ...