AVL数
平衡二叉树(AVL树)
AVL树是一种二叉搜索树,并且每个节点的左右子树高度之差最多为1。AVL树是第一个在最坏的情况下保证以O(logn)的时间进行搜索,插入和删除操作的数据结构,AVL树能在对数时间内完成操作的主要思想是在插入和删除的时候花一些时间来保持树的平衡,使树的高度总在O(logn)范围内
插入后不满足AVL树的情况
令x是要插入AVL树种的关键字,首先将x插入树的底部,如果插入后仍是AVL树,则没有问题,否则要对数进行平衡。假设节点A的左子树和右子树在插入后失去平衡(高度差为2),这将分四种情况:
- 对A的左孩子的左子树进行了一次插入
- 对A的左孩子的右子树进行了一次插入
- 对A的右孩子的左子树进行了一次插入
- 对A的右孩子的右字树进行了一次插入
其中第一和第四种情形对称,第二和第三种情形对称,第一,四可以通过一次单旋转完成调整,
下图是其中两种,剩两种与它们右对称

- 图(a)插入新节点后,B树的高度是h+2,C树高度是h,为了保持树的平衡需要进行旋转,将B转到树顶,然后根据二叉搜索树的性质调整树的其他部分.

- 图(b)插入节点后,旋转一个位置不够,需要旋转两个位置. 首先对B进行顺时针旋转,然后对A作顺时针旋转

顺时针和逆时针旋转两种方式:

双旋转的方式
(首先对B进行逆时针旋转,然后对A进行顺时针旋转)
(首先对B进行顺时针旋转,然后对A进行逆时针旋转)上面两个例子中 A被称作关键节点
关键节点: 它是插入操作之后非AVL树的最小树的根节点,在插入节点之前必须找到关键节点,从而判断是哪种情况。于是我们在每个节点中记录一个平衡因子,即左右子树的高度之差.对AVL树而言,任意一个节点的平衡因子只能是1,-1或0. 关键节点的平衡因子一定不是0,并且在平衡后高度与插入前相同

源代码namespace AVLTree
{
public class Node
{
public int Value;
public Node Left;
public Node Right;
public int Factor; }
public class AVLTree
{
private Node root; private Node ParentNode(int x)
{
Node node = root;
Node parent = null;
while (node != null)
{
if (node.Value == x)
{
return parent;
} parent = node;
if (node.Value > x)
{
node = node.Left;
}
else
{
node = node.Right;
}
}
throw new Exception(string.Format("{0} has no parent", x));
} public void Insert(int x)
{
Insert(ref root,x);
} private void Insert(ref Node tree, int x)
{
Node node = new Node() { Value = x };
if (tree == null)
{
tree = node;
}
if (tree.Value > x)
{
Insert(ref tree.Left,x); if (Depth(tree.Left) - Depth(tree.Right) == 2)
{
if (tree.Left.Value > x)
{
R_Rotate(tree);
}
else if (tree.Left.Value < x)
{
LR_Rotate(tree);
}
}
} else if (tree.Value < x)
{
Insert(ref tree.Right,x); if (Depth(tree.Right) - Depth(tree.Left) == 2)
{
if (tree.Right.Value < x)
{
L_Rotate(tree);
}
else if (tree.Right.Value > x)
{
RL_Rotate(tree);
}
}
}
} public void L_Rotate(Node tree)
{
Node parent = ParentNode(tree.Value);
Node lr = tree.Right;
tree.Right = lr.Left; lr.Left = tree; if (parent != null)
{
if (Object.ReferenceEquals(parent.Left, tree))
{
parent.Left = lr;
}
else if (Object.ReferenceEquals(parent.Right, tree))
{
parent.Right = lr;
}
}
else
{
root = tree;
} } public void R_Rotate( Node tree)
{
Node parent = ParentNode(tree.Value);
Node lc = tree.Left; tree.Left = lc.Right;
lc.Right = tree; if (parent != null)
{
if (Object.ReferenceEquals(parent.Left, tree))
{
parent.Left = lc;
}
else if (Object.ReferenceEquals(parent.Right, tree))
{
parent.Right = lc;
}
}
else
{
root = lc;
}
} public void LR_Rotate(Node tree)
{
L_Rotate(tree.Left);
R_Rotate(tree);
} public void RL_Rotate(Node tree)
{
R_Rotate(tree.Right);
L_Rotate(tree);
} private int Depth(Node tree)
{
if (tree == null) return 0;
else
{
int dleft = Depth(tree.Left);
int dright = Depth(tree.Right);
return (dleft > dright ? dleft + 1 : dright + 1);
}
} public override string ToString()
{
return Tree(root);
} private string Tree(Node node)
{
if (node == null)
{
return string.Empty;
} string left = Tree(node.Left);
string right = Tree(node.Right);
if (!string.IsNullOrEmpty(left) || !string.IsNullOrEmpty(right))
{
return string.Format("{0}({1},{2})", node.Value, Tree(node.Left), Tree(node.Right));
}
else
{
return node.Value.ToString();
}
} public static void Swap(ref int x, ref int y)
{
int temp = x;
x = y;
y = temp;
}
}
}
AVL数的更多相关文章
- 51nod 1412 AVL数的种类(DP
题意给了n个节点 问AVL树的种类 卧槽 真的好傻 又忘记这种题可以打表了 就算n^3 也可以接受的 树的深度不大 那么转移方程很明显了 dp[i][j] 代表的是节点为n深度为j的树的种类 k ...
- java平衡二叉树AVL数
平衡二叉树(Balanced Binary Tree)具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树 右旋:在插入二叉树的时候,根节点的右侧高 ...
- PAT甲级题解-1066. Root of AVL Tree (25)-AVL树模板题
博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6803291.html特别不喜欢那些随便转载别人的原创文章又不给 ...
- AVL平衡二叉搜索树原理及各项操作编程实现
C语言版 #include<stdio.h> #include "fatal.h" struct AvlNode; typedef struct AvlNode *Po ...
- BST AVL RBT B- B+ 的一些理解
BST(二叉查找树,排序二叉树),如果数据有序的话,组成的二叉树会形成单列的形式,导致查询效率低AVL(平衡二叉树) 使树的左右高度差的绝对值不超过2,保证了查询效率.但是插入和删除会带来多次旋转,导 ...
- 浅谈时间复杂度- 算法衡量标准Big O
写在前面: 今天有一场考试,考到了Big-O的知识点,考到了一道原题,原题的答案我记住了,但实际题目有一些改动导致答案有所改动,为此作者决定重新整理一下复杂度相关知识点 Efficiency and ...
- 《剑指offer(第二版)》面试题55——判断是否为平衡二叉树
一.题目大意 输入一颗二叉树,判断该二叉树是否为平衡二叉树(AVL树). 二.题解 <剑指offer>上给出了两种解决方式: 1.第一种是从根节点开始,从上往下遍历每个子节点并计算以子节点 ...
- 面试可能遇到的关联式容器(map、set等)相关问题
>>>. map与set的区别是什么,各有哪些优势? map中存储的数据是以键值对(key - value)形式并且通过排序(比较key,默认以 '<' 方式排序)存在的( ...
- Leetcode No.108 Convert Sorted Array to Binary Search Tree(c++实现)
1. 题目 1.1 英文题目 Given an integer array nums where the elements are sorted in ascending order, convert ...
随机推荐
- hdu1385 Minimum Transport Cost 字典序最小的最短路径 Floyd
求最短路的算法最有名的是Dijkstra.所以一般拿到题目第一反应就是使用Dijkstra算法.但是此题要求的好几对起点和终点的最短路径.所以用Floyd是最好的选择.因为其他三种最短路的算法都是单源 ...
- 获取listview的高度代码
public int getTotalHeightofListView(ListView listView) { ListAdapter mAdapter = (ListAdapter) listVi ...
- 基于S3C2440数码相框
[参考]韦东山 教学笔记 1. 程序框架1.1 触摸屏: 主按线程,通过socket发给显示进程 --------------------------- 封装事件:ts线程 按键线程 -------- ...
- MemCached总结三:PHP的memcached管理接口
在Web系统中应用MemCached缓存技术,必须使用客户端API(PHP)进行访问,这样才能将用户请求的动态数据,缓存到memcached服务器中,来减少对数据库的访问压力.PHP中提供了用于内存缓 ...
- chrome模拟微信
这里有一个模拟器,既可以设置模拟很多型号的手机设备,也可以伪造你想要的HTTP_USER_AGENT.选择USER_AGENT,选other,微信的HTTP_USER_AGENT是: 在iPhone下 ...
- 07 --C语言字符串函数
1)字符串操作 复制 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strdup(char *str) 将串拷贝到新建的位置处 ...
- Java中面向对象三大特性之——封装
概述 面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改. 封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问.要访问该类的数据,必须通 ...
- day09网络编程
一 操作系统基础 操作系统:(Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才 ...
- HDU1527 - 取石子游戏【威佐夫博弈】
有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后把石子全部取完者为胜者. ...
- [luogu2081 NOI2012] 迷失游乐园 (树形期望dp 基环树)
传送门 题目描述 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩. 进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m ...