AVL平衡树(非指针实现)
看了网上三四篇博客,学习了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平衡树(非指针实现)的更多相关文章
- 实现Avl平衡树
实现Avl平衡树 一.介绍 AVL树是一种自平衡的二叉搜索树,它由Adelson-Velskii和 Landis于1962年发表在论文<An algorithm for the organi ...
- BZOJ3223文艺平衡树——非旋转treap
此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...
- Python与数据结构[3] -> 树/Tree[2] -> AVL 平衡树和树旋转的 Python 实现
AVL 平衡树和树旋转 目录 AVL平衡二叉树 树旋转 代码实现 1 AVL平衡二叉树 AVL(Adelson-Velskii & Landis)树是一种带有平衡条件的二叉树,一棵AVL树其实 ...
- 数据结构学习-AVL平衡树
环境:C++ 11 + win10 IDE:Clion 2018.3 AVL平衡树是在BST二叉查找树的基础上添加了平衡机制. 我们把平衡的BST认为是任一节点的左子树和右子树的高度差为-1,0,1中 ...
- AVL平衡树的插入例程
/* **AVL平衡树插入例程 **2014-5-30 11:44:50 */ avlTree insert(elementType X, avlTree T){ if(T == NULL){ T = ...
- 【转】 史上最详尽的平衡树(splay)讲解与模板(非指针版spaly)
ORZ原创Clove学姐: 变量声明:f[i]表示i的父结点,ch[i][0]表示i的左儿子,ch[i][1]表示i的右儿子,key[i]表示i的关键字(即结点i代表的那个数字),cnt[i]表示i结 ...
- AVL 平衡树
AVL是一种平衡二叉树,它通过对二叉搜索树中的节点进行旋转使得二叉搜索树达到平衡.AVL在所有的平衡二叉搜索树中具有最高的平衡性. 定义 平衡二叉树或者为空树或者为满足如下性质的二叉搜索树: 左右子树 ...
- 伸展树Splay【非指针版】
·伸展树有以下基本操作(基于一道强大模板题:codevs维护队列): a[]读入的数组;id[]表示当前数组中的元素在树中节点的临时标号;fa[]当前节点的父节点的编号;c[][]类似于Trie,就是 ...
- BZOJ3224普通平衡树——非旋转treap
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...
随机推荐
- 采样方法(二)MCMC相关算法介绍及代码实现
采样方法(二)MCMC相关算法介绍及代码实现 2017-12-30 15:32:14 Dark_Scope 阅读数 10509更多 分类专栏: 机器学习 版权声明:本文为博主原创文章,遵循CC 4 ...
- JAVA学习篇--静态代理VS动态代理
本篇博客的由来,之前我们学习大话设计,就了解了代理模式,但为什么还要说呢? 原因: 1,通过DRP这个项目,了解到了动态代理,认识到我们之前一直使用的都是静态代理,那么动态代理又有什么好处呢?它们二者 ...
- Partial的应用
Partial是局部类型的意思.允许我们将一个类.结构或接口分成几个部分,分别实现在几个不同的.cs文件中.C#编译器在编译的时候仍会将各个部分的局部类型合并成一个完整的类 局部类型的注意点1. 局部 ...
- .Net下二进制形式的文件存储与读取
.Net下图片的常见存储与读取凡是有以下几种:存储图片:以二进制的形式存储图片时,要把数据库中的字段设置为Image数据类型(SQL Server),存储的数据是Byte[].1.参数是图片路径:返回 ...
- 给枚举定义DescriptionAttribute
在C#中,枚举用来定状态值很方便,例如我定义一个叫做Season的枚举 public enum Season { Spring = 1, Summer = 2, Autumn = 3, Winter ...
- python 识别图像主题并切割
两种办法,一种是用百度的API,效果还可以,不过好像每天有50次的调用的限制 from aip import AipImageClassify import cv2 """ ...
- SPOJ-MobileService--线性DP
题目链接 https://www.luogu.org/problemnew/show/SP703 方法一 分析 很显然可以用一个四维的状态\(f[n][a][b][c]\)表示完成第i个任务时且三人 ...
- json树迭代
getArray(data){ for (var i in data) { if(data[i].disabled){ data[i].disabled = false } if(data[i].ch ...
- ASE19团队项目alpha阶段model组 scrum5 记录
本次会议于11月7日,19时整在微软北京西二号楼sky garden召开,持续12分钟. 与会人员:Jiyan He, Kun Yan, Lei Chai, Linfeng Qi, Xueqing W ...
- 【Java并发】锁机制
一.重入锁 二.读写锁 三.悲观锁.乐观锁 3.1 悲观锁 3.2 乐观锁 3.3 CAS操作方式 3.4 CAS算法理解 3.5 CAS(乐观锁算法) 3.6 CAS缺点 四.原子类 4.1 概述 ...