一. AVL概念:
对于一颗BST,其中每个节点的左右子树高度差均不超过1的平衡二叉搜索树,就叫做AVL树。
二. 如何维护一颗AVL树。
旋转操作:
1. rotateWithLeft:(右旋转)
* (N) (L)
* / \ / \
* (L) 3 ==> 1 (N)
* / \ / \
* 1 2 2 3
2. rotateWithRight:(左旋转)
* (N) (R)
* / \ / \
* 1 (R) ==> (N) 3
* / \ / \
* 2 3 1 2
三.AVL的基本操作:
Find(x,AVL);//在AVL树中查找值为X的元素
Insert(x,&AVL);//在AVL树中插入值为X的元素
Remove(x,&AVL);//在AVL树中删除值为X的元素
FindMax(AVL);//查找AVL树中的最大值
FindMin(AVL);//查找AVL树中的最小值
rotateWithLeft(&node);//右旋
rotateWithRight(&node)//左旋
四.AVL的静态实现:
1.用到的数据结构:int left[],right[],next[],height[],data[].
2.说明: left,right分别保存节点的左子结点和右子结点,0表示空,height保存某一结点的 高度,用来计算平衡因子,data保存结点的数据.
3.实现分析:
(1).FindMax,Find,FindMin,和BST的一样。
(2).Insert,将元素插入AVL树后,沿插入路径逆向,从插入位置开始,遇到第一个不平 衡的结点就将该子树旋转至平衡,如此操作,整棵AVL都达到平衡。
(3).Remove,先仿造BST的删除方式进行删除,从删除位置沿删除路径返回根节点,只要遇到不平衡的结点就旋转.
(4).旋转操作,不平衡的点一定有孙子,祖父与孙子共线: 单旋转;祖父与孙子不共线: 双旋转。(图来自刘汝佳的书《高级数据结构》)
单旋转:
双旋转:
五.实现代码:
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
#define SIZE 100
#define MAX(a,b) a>b?a:b
/**
** author: yfr
** date: 2012-1-9
** project: AVL tree
** reference: LRJ's BOOK
** 用数组模拟链式结构(姑且用静态这个说法),实现AVL的插入操作
** 这里不直接用平衡因子,而是保持树各结点的高度,然后去计算平衡因子
** 空树的高度是-1
**/
int Left[SIZE],Right[SIZE],next[SIZE],data[SIZE],height[SIZE];
/*辅助容器*/
vector<int> look[SIZE];
int depth[SIZE];
/**/
/**
所有操作申明
**/
void Init();
int makenode(int x);
void delnode(int);
int find(int x,int p);
int findmin(int);
int findmax(int);
void insert(int x,int &p);
void remove(int x,int &p);
//初始化各数组
void Init()
{
memset(Left,0,sizeof(Left));
memset(Right,0,sizeof(Right));
memset(height,-1,sizeof(height));//空树高度为-1
for(int i=0;i<SIZE;i++)
next[i] = i+1;
}
//模拟内存分配函数
int makenode(int x)
{
int p = next[0];
next[0] = next[p];
data[p] = x;
return p;
}
void delnode(int p)
{
Left[p] = Right[p] = 0;
height[p] = -1;
next[p] = next[0];
next[0] = p;
}
//AVL的操作函数
/*旋转
a b
\ / \
b ------------> a c
/ \ /
d c d
*/
void rotateWithRight(int &p)
{
int q = Right[p];
Right[p] = Left[q];
Left[q] = p;
height[p] = MAX(height[Left[p]],height[Right[p]])+1;
height[q] = MAX(height[Right[q]],height[p])+1;
p = q;//
}
/*旋转
a b
/ / \
b -------------> c a
/ \ /
c d d
*/
void rotateWithLeft(int &p)
{
int q = Left[p];
Left[p] = Right[q];
Right[q] = p;
height[p] = MAX(height[Left[p]],height[Right[p]])+1;
height[q] = MAX(height[Left[q]],height[p])+1;
p = q;
}
void insert(int x,int &p)
{
if(!p)
{
p = makenode(x);
height[p] = MAX(height[Left[p]],height[Right[p]])+1;
return;
}
if(x < data[p])
{
insert(x,Left[p]);
height[p] = MAX(height[Left[p]],height[Right[p]])+1;
if(height[Left[p]]-height[Right[p]]==2)//不平衡
{
if(height[Left[Left[p]]]-height[Right[Left[p]]]==1)//LL
{
rotateWithLeft(p);
}
else if(height[Left[Left[p]]]-height[Right[Left[p]]]==-1)//LR
{
rotateWithRight(Left[p]);
rotateWithLeft(p);
}
}
}
else
{
insert(x,Right[p]);
height[p] = MAX(height[Left[p]],height[Right[p]])+1;
if(height[Left[p]]-height[Right[p]]==-2)//不平衡
{
if(height[Left[Right[p]]]-height[Right[Right[p]]]==1)//RL
{
rotateWithLeft(Right[p]);
rotateWithRight(p);
}
else if(height[Left[Right[p]]]-height[Right[Right[p]]]==-1)//RR
{
rotateWithRight(p);
}
}
}
}
//从AVL树中删除节点
//先删除,再调整树形
void remove(int x,int &p)
{
if(!p) return;//如果是空树,返回
if(x < data[p]){
remove(x,Left[p]);
}
else if(x > data[p]){
remove(x,Right[p]);
}
else//如果已经找到该结点
{
if(Left[p]&&Right[p])//如果左右结点非空
{
int q = findmin(Right[p]);
data[p] = data[q];
remove(data[p],Right[p]);
}
else
{
int q = p;
p = Left[p]?Right[p]:Left[p];
delnode(q);//释放该结点
return;//删除处的高度不需要调整
}
}
if(p){//如果不是空树的话
height[p] = MAX(height[Left[p]],height[Right[p]])+1;//记录高度
//不平衡则旋转
if(height[Left[p]]-height[Right[p]]==2)//L
{
if(height[Left[Left[p]]]-height[Right[Left[p]]]>=0)//L
{
rotateWithLeft(p);//LL旋转
}
else//R
{
//LR旋转
rotateWithRight(Left[p]);
rotateWithLeft(p);
}
}
else if(height[Left[p]]-height[Right[p]]==-2)//R
{
if(height[Left[Right[p]]]-height[Right[Right[p]]]<=0)//RR
{
rotateWithRight(p);
}
else
{
//RL
rotateWithLeft(Right[p]);
rotateWithRight(p);
}
}
}
}
int find(int x,int p)
{
if(!p)return 0;
if(x == data[p]) return p;
if(x < data[p]) return find(x,Left[p]);
if(x > data[p]) return find(x,Right[p]);
}
int findmin(int p)
{
if(!p)return 0;//空树
if(!Left[p]) return p;
else return findmin(Left[p]);
}
int findmax(int p)
{
if(p)
while(Right[p]) p = Right[p];
return p;
}
/*********************
辅助函数
**********************/
//标记好各结点的层数,查看树形时要用到
void dfs(int p,int deep)
{
if(!p)return;
depth[p] = deep;
dfs(Left[p],deep+1);
dfs(Right[p],deep+1);
}
void order(int p)
{
if(!p)return;
order(Left[p]);
cout<<data[p]<<endl;
order(Right[p]);
}
//查看树形
void bfs(int p)
{
dfs(p,0);
queue<int> q;
q.push(p);
while(!q.empty())
{
int v = q.front();
q.pop();
if(Left[v])q.push(Left[v]);
if(Right[v])q.push(Right[v]);
cout<<data[v]<<endl;
look[depth[v]].push_back(data[v]);
}
}
void print_tree(int deep)
{
for(int i=0;i<=deep;i++)
{
for(int j=0;j<look[i].size();j++)
{
cout<<look[i][j];
for(int k=0;k<=deep-i;k++)
cout<<" ";
}
cout<<endl;
}
}
int main()
{
freopen("dataout.txt","w",stdout);
Init();
int ROOT = 0;
insert(10,ROOT);//build AVLtree
insert(11,ROOT);
insert(12,ROOT);
insert(13,ROOT);
insert(14,ROOT);
remove(10,ROOT);
bfs(ROOT);
print_tree(height[ROOT]);
return 0;
}
- 大小: 80.4 KB
- 大小: 62.4 KB
分享到:
相关推荐
在本项目中,我们将讨论如何结合这两种数据结构,利用avl树实现哈希表,以达到更好的性能效果。 首先,让我们了解一下avl树。avl树是一种自平衡二叉搜索树(BST),它的特点是任何节点的两个子树的高度最大差别不...
AVL树是一种自平衡的...总结来说,AVL树的C++实现是一个包含节点类、树类和相关操作实现的过程。通过理解和实现这个过程,你可以深入理解自平衡二叉搜索树的工作原理,并能够灵活地在自己的项目中应用这些数据结构。
在C语言中实现AVL树,首先需要定义AVL树的节点结构。每个节点包含三个部分:存储数据的关键字(key)、节点的高度(height)以及指向左子树和右子树的指针。一个简单的节点定义如下: ```c typedef struct AVLNode ...
AVL树是一种自平衡二叉查找树(Self-Balancing Binary Search Tree),由G. M. Adelson-Velsky和E. M. Landis在1962年提出,因此得名AVL树,它是最早的自平衡二叉查找树之一。在AVL树中,任意节点的两个子树的高度差...
基于C++的AVL树实现,
一个avltree的简单实现,便于了解avltree的结构及应用
学习AVL树的算法实现,使用c++在vc6.0中进行相应的算法实现,对正在学习算法的孩子有帮助
在C++中实现AVL树,我们需要关注以下几个关键点: 1. **节点结构**:AVL树中的每个节点包含一个键值、指向左子树和右子树的指针,以及表示该节点平衡因子的整数值。平衡因子是节点的左子树高度减去右子树高度。典型...
本设计实现了AVLTree的所有的实现功能,也包括BinSTree与AVLTree的转换
AVL树是一种自平衡二叉查找树(Binary Search Tree,BST),由Georgy Adelson-Velsky和Emanuel Land...相比于标准库中的红黑树实现,AVL树在保持平衡方面更严格,可能在某些操作上表现得更快,但实现和维护也更为复杂。
7. **调试和测试**:在C#2005中,确保AVL树的实现正确性至关重要,可以通过插入一系列已知的数据,然后进行查找、插入和删除操作,检查结果是否符合预期。同时,调试过程中应关注旋转逻辑,确保每次操作后树依然保持...
在C++中实现AVL树,我们通常会使用模板类来实现泛型编程,这样可以使得AVL树能够处理不同类型的元素。以下是一个基本的AVL树节点定义: ```cpp template struct AVLNode { T data; int height; AVLNode* left; ...
在C语言中实现AVL树,我们需要关注以下几个关键点: 1. **数据结构定义**:首先,我们需要定义一个结构体来表示AVL树的节点。这个结构体通常包含元素值、节点高度、左子树指针、右子树指针以及平衡因子(左子树高度...
在给定的代码中,主要展示了AVL树的插入操作的实现。 首先,我们看到`avlInsert`函数用于在AVL树中插入一个新节点。这个函数首先检查树是否为空,如果为空,则直接创建一个新节点作为树的根节点。接着,通过循环...
在C#中实现AVL树,首先需要理解二叉查找树的基本概念和操作。二叉查找树是一种特殊的二叉树,其中每个节点都包含一个键(key)、一个关联的值、一个指向左子树的指针和一个指向右子树的指针。在二叉查找树中,每个...
AVL树是一种自平衡二叉查找树(Binary Search Tree,...以上是C++实现AVL树的基础知识点,具体实现过程会涉及更多细节,如旋转的具体代码实现、错误处理等。在实际编码时,还需要注意C++语法和面向对象设计原则的运用。
本话题主要探讨了C++实现的二叉树、二叉搜索树以及AVL树,这些都是高级数据结构,对于优化算法和提高程序效率至关重要。 二叉树是一种特殊的树结构,每个节点最多只有两个子节点,通常分为左子节点和右子节点。在...
在`avl_tree`这个文件中,很可能包含了AVL树的C++、Java或Python等编程语言的实现,包括节点定义、插入、删除和以括号表示法输出等功能。通过阅读和理解这些代码,你可以深入学习AVL树的工作原理和实际应用。