平衡二叉树(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数的更多相关文章

  1. 51nod 1412 AVL数的种类(DP

    题意给了n个节点 问AVL树的种类 卧槽 真的好傻 又忘记这种题可以打表了  就算n^3 也可以接受的 树的深度不大 那么转移方程很明显了 dp[i][j]   代表的是节点为n深度为j的树的种类 k ...

  2. java平衡二叉树AVL数

    平衡二叉树(Balanced Binary Tree)具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树 右旋:在插入二叉树的时候,根节点的右侧高 ...

  3. PAT甲级题解-1066. Root of AVL Tree (25)-AVL树模板题

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6803291.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  4. AVL平衡二叉搜索树原理及各项操作编程实现

    C语言版 #include<stdio.h> #include "fatal.h" struct AvlNode; typedef struct AvlNode *Po ...

  5. BST AVL RBT B- B+ 的一些理解

    BST(二叉查找树,排序二叉树),如果数据有序的话,组成的二叉树会形成单列的形式,导致查询效率低AVL(平衡二叉树) 使树的左右高度差的绝对值不超过2,保证了查询效率.但是插入和删除会带来多次旋转,导 ...

  6. 浅谈时间复杂度- 算法衡量标准Big O

    写在前面: 今天有一场考试,考到了Big-O的知识点,考到了一道原题,原题的答案我记住了,但实际题目有一些改动导致答案有所改动,为此作者决定重新整理一下复杂度相关知识点 Efficiency and ...

  7. 《剑指offer(第二版)》面试题55——判断是否为平衡二叉树

    一.题目大意 输入一颗二叉树,判断该二叉树是否为平衡二叉树(AVL树). 二.题解 <剑指offer>上给出了两种解决方式: 1.第一种是从根节点开始,从上往下遍历每个子节点并计算以子节点 ...

  8. 面试可能遇到的关联式容器(map、set等)相关问题

    >>>. map与set的区别是什么,各有哪些优势?   map中存储的数据是以键值对(key - value)形式并且通过排序(比较key,默认以 '<' 方式排序)存在的( ...

  9. 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 ...

随机推荐

  1. c# 异步任务队列(可选是否使用单线程执行任务,以及自动取消任务)

    使用demo,(.net framework 4.0 自行添加async wait 扩展库) class Program { static void Main(string[] args) { Con ...

  2. python 整型,布尔值,字符串相关

    1.整型(int) 就是所有整数, 2.布尔值(bool) True False 0,"",[],{},(),none为False 3.字符串(str) 字符: 是单一文字符号 字 ...

  3. MindManager 2019新版上市 ,了解一下!

    所有的等待都是值得的!MindManager在蓄力一年后,给各位思维导图爱好者带来了全新的MindManager 2019 for Windows.全新的版本包含英语.德语.法语.俄语.中文.日语,新 ...

  4. Nginx的安装与升级

    1,构建Nginx服务器; 2.升级版本; 一, 构建Nginx服务器 1.使用源码包安装nginx软件包 # yum -y install gcc pcre-devel openssl-devel  ...

  5. PowerDesigner工具

    PowerDesigner是一款数据库设计与建模工具,开发人员可以在上面设计表结构,而不用一开始就创建数据库中的表,因为设计阶段数据库表结构会经常变动.设计完后可以导出创建所有表的SQL脚本,直接执行 ...

  6. 封装自己的jquery框架

    jQuery is a fast small JavaScript library 如何封装自己的jQuery <script> // 这里使用沙箱模式,可以防止全局污染 (functio ...

  7. JAVA 上传图片功能

    前后端实现上传图片功能(JAVA代码) 1.前端大概 请求头必须为AJAX请求头: 'X-Requested-With': 'XMLHttpRequest' 一般是指网页中存在的Content-Typ ...

  8. VUEX 总结

    What is Vuex? vuex是一个专为Vue.js应用程序开发的状态管理模式.他采用集中式储存管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变换 VUEX并不限制你的代 ...

  9. eclipse debug的时候提示debug Edit Source Lookup path

    原因可能是代码资源包未加载到debug的路径中,解决方法如下: Debug 视图下 ->在调试的线程上 右键单击 ->选择Edit Source Lookup Path ->选择Ad ...

  10. 做支付遇到的HttpClient大坑

    前言 HTTPClient大家应该都很熟悉,一个很好的抓网页,刷投票或者刷浏览量的工具.但是还有一项非常重要的功能就是外部接口调用,比如说发起微信支付,支付宝退款接口调用等:最近我们在这个工具上栽了一 ...