看了网上三四篇博客,学习了AVL树维护平衡的方式。但感觉他们给出的代码都有一点瑕疵或者遗漏,懂得了思想之后,花了一些时间把他们几篇的长处结合起来,没有使用指针,实现了一下。每个小逻辑功能都抽象成了函数,应该比较好理解,代码逻辑看起来也比较清晰。
下面给出主要的功能插入和删除。至于其他一些没有动到树结构的操作,如查询,求前驱后继等,同其他BST,没有什么特别。
这里顺带一提,下面的代码中,没有维护子树size,如果要求第K小或者名次,可以在upd函数等处添加有关size的维护,之后便可以支持相关查询了。

#include<iostream>
#include<algorithm>
#define de(x) cout<<#x<<" = "<<x<<endl
using namespace std;
const int maxn=1e5+10;
struct AVL
{
int key,h,lc,rc;
}tree[maxn];
int id,root;
inline int newNode(int k,int l,int r)
{
tree[++id].key=k;
tree[id].lc=l;
tree[id].rc=r;
tree[id].h=0;
return id;
}
inline int height(int id)
{
return id ? tree[id].h : 0;
}
inline void upd(int id)
{
if (!id)
return;
int lh=height(tree[id].lc), rh=height(tree[id].rc);
tree[id].h=max(lh, rh)+1;
}
inline int rightRotate(int id)
{
int lc=tree[id].lc;
tree[id].lc=tree[lc].rc;
tree[lc].rc=id;
upd(id);
upd(lc);
return lc;
}
inline int leftRotate(int id)
{
int rc=tree[id].rc;
tree[id].rc=tree[rc].lc;
tree[rc].lc=id;
upd(id);
upd(rc);
return rc;
}
inline int lrRotate(int id)
{
tree[id].lc=leftRotate(tree[id].lc);
return rightRotate(id);
}
inline int rlRotate(int id)
{
tree[id].rc=rightRotate(tree[id].rc);
return leftRotate(id);
}
inline int balance(int id)
{
if (height(tree[id].lc)-height(tree[id].rc) > 1)
{
int lc=tree[id].lc;
if (height(tree[lc].lc) > height(tree[lc].rc))
return rightRotate(id);
else
return lrRotate(id);
}
else if (height(tree[id].rc)-height(tree[id].lc) > 1)
{
int rc=tree[id].rc;
if (height(tree[rc].lc) < height(tree[rc].rc))
return leftRotate(id);
else
return rlRotate(id);
}
return id;
}
int getMax(int id)
{
if (!id)
return 0;
while (tree[id].rc)
id=tree[id].rc;
return id;
}
int getMin(int id)
{
if (!id)
return 0;
while (tree[id].lc)
id=tree[id].lc;
return id;
}
void insert(int& rt, int v)
{
if (!rt)
rt=newNode(v,0,0);
else if (v < tree[rt].key)
insert(tree[rt].lc, v);
else if (v > tree[rt].key)
insert(tree[rt].rc, v);
rt=balance(rt);
upd(rt);
return;
}
void del(int& rt, int v)
{
if (!rt)
return;
if (v < tree[rt].key)
del(tree[rt].lc, v);
else if (v > tree[rt].key)
del(tree[rt].rc, v);
else
{
if (tree[rt].lc&&tree[rt].rc)
{
if (height(tree[rt].lc) > height(tree[rt].rc))
{
int maxId=getMax(tree[rt].lc);
tree[rt].key=tree[maxId].key;
del(tree[rt].lc, tree[maxId].key);
}
else
{
int minId=getMin(tree[rt].rc);
tree[rt].key=tree[minId].key;
del(tree[rt].rc, tree[minId].key);
}
}
else
rt=tree[rt].lc ? tree[rt].lc : tree[rt].rc;
}
rt=balance(rt);
upd(rt);
}

AVL平衡树(非指针实现)的更多相关文章

  1. 实现Avl平衡树

    实现Avl平衡树   一.介绍 AVL树是一种自平衡的二叉搜索树,它由Adelson-Velskii和 Landis于1962年发表在论文<An algorithm for the organi ...

  2. BZOJ3223文艺平衡树——非旋转treap

    此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...

  3. Python与数据结构[3] -> 树/Tree[2] -> AVL 平衡树和树旋转的 Python 实现

    AVL 平衡树和树旋转 目录 AVL平衡二叉树 树旋转 代码实现 1 AVL平衡二叉树 AVL(Adelson-Velskii & Landis)树是一种带有平衡条件的二叉树,一棵AVL树其实 ...

  4. 数据结构学习-AVL平衡树

    环境:C++ 11 + win10 IDE:Clion 2018.3 AVL平衡树是在BST二叉查找树的基础上添加了平衡机制. 我们把平衡的BST认为是任一节点的左子树和右子树的高度差为-1,0,1中 ...

  5. AVL平衡树的插入例程

    /* **AVL平衡树插入例程 **2014-5-30 11:44:50 */ avlTree insert(elementType X, avlTree T){ if(T == NULL){ T = ...

  6. 【转】 史上最详尽的平衡树(splay)讲解与模板(非指针版spaly)

    ORZ原创Clove学姐: 变量声明:f[i]表示i的父结点,ch[i][0]表示i的左儿子,ch[i][1]表示i的右儿子,key[i]表示i的关键字(即结点i代表的那个数字),cnt[i]表示i结 ...

  7. AVL 平衡树

    AVL是一种平衡二叉树,它通过对二叉搜索树中的节点进行旋转使得二叉搜索树达到平衡.AVL在所有的平衡二叉搜索树中具有最高的平衡性. 定义 平衡二叉树或者为空树或者为满足如下性质的二叉搜索树: 左右子树 ...

  8. 伸展树Splay【非指针版】

    ·伸展树有以下基本操作(基于一道强大模板题:codevs维护队列): a[]读入的数组;id[]表示当前数组中的元素在树中节点的临时标号;fa[]当前节点的父节点的编号;c[][]类似于Trie,就是 ...

  9. BZOJ3224普通平衡树——非旋转treap

    题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...

随机推荐

  1. Docker 容器学习笔记

    Docker 诞生于2013年,最初发起者是dotCloud公司.Docker自开源后受到广泛的关注和讨论,目前已有多个相关项目逐渐形成了围绕Docker容器的生态体系,由于Docker在业界造成的影 ...

  2. ACM-ICPC 2017北京

    J. Pangu and Stones 大意: 给定$n$堆石子, $(n\le 100)$, 每次操作任选连续的至少$L$堆至多$R$堆合并, 代价为合并石子的总数, 求合并为$1$堆的最少花费. ...

  3. Go入门所踩过的坑:cannot find package "" in any of

    问题:cannot find package "" in any of.现已按照博客解决,分享一种自己踩得坑欢迎大神指导交流! 首先使用go env查看当前环境变量,新手入门出现找 ...

  4. SQL连接(join)

    INNER JOIN:如果表中有至少一个匹配,则返回行 LEFT JOIN:即使右表中没有匹配,也从左表返回所有的行 RIGHT JOIN:即使左表中没有匹配,也从右表返回所有的行 FULL JOIN ...

  5. [转载]clip gradient抑制梯度爆炸

    [转载]clip gradient抑制梯度爆炸 来源:https://blog.csdn.net/u010814042/article/details/76154391 1.梯度爆炸的影响 在一个只有 ...

  6. oracle导入时IMP-00010: 不是有效的导出文件, 头部验证失败

    头部验证失败是由于版本号不同所致,经试验可以通过如下方法进行修改:用notepad++工具打开dmp文件,可以看到头部信息 --TEXPORT:V11.01.00,即为源数据库的版本号,将其修改为目的 ...

  7. 一个SDL2.0程序的分析

    //把图片加载到SDL_Texture SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren){       ...

  8. 如何检测浏览器是否能用ActiveX

    var xhr=false; function CreateXHR(){ try{ //检查能否用activexobject xhr=new ActiveXObject("msxml2.XM ...

  9. 4.SpringMVC 配置式开发-处理器映射器

    处理器映射器 HandlerMapping HandlerMapping 接口负责根据request请求找到对应的Handler处理器及Interceptor拦截器, 并将它们封装在HandlerEx ...

  10. vs code 开发小程序会用到的插件

    主要介绍一下几个vscode插件,在vscode中搜索插件关键字点击安装即可. 1) vscode weapp api,  语法结构api; 2) minapp-vscode 3) vscode wx ...