平衡二叉树(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. Session和Cookie对比详解

    会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...

  2. Zabbix4.0 Web管理界面中文乱码解决方法(转)

    Zabbix安装好之后,监控图形页面出现字符集乱码 解决方法:1.复制本地电脑C:\Windows\Fonts\simkai.ttf(楷体)上传到zabbix服务器网站目录的fonts目录下 2.za ...

  3. buddyinfo 内存碎片数据采集

    不说了,上工具 #cat buddyinfo.sh #!/bin/sh #*************************************************************** ...

  4. vue 面试题 2019

    vue核心知识点 1.对于Vue是一套渐进式框架的理解 渐进式代表的含义是:主张最少. Vue可能有些方面是不如React,不如Angular,但它是渐进的,没有强主张,你可以在原有大系统的上面,把一 ...

  5. HDU 1385 Minimum Transport Cost( Floyd + 记录路径 )

    链接:传送门 题意:有 n 个城市,从城市 i 到城市 j 需要话费 Aij ,当穿越城市 i 的时候还需要话费额外的 Bi ( 起点终点两个城市不算穿越 ),给出 n × n 大小的城市关系图,-1 ...

  6. HDU 5901 Count primes( Meisell-Lehmer算法模板 )

    链接:传送门 题意:计算 [ 1 , n ] 之间素数的个数,(1 <= n <= 1e11) 思路:Meisell-Lehmer算法是计算超大范围内素数个数的一种算法,原理并不明白,由于 ...

  7. 训练1-A

    一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢? Input 输入中含有一些数据,分别是成对出现的花布条和 ...

  8. 学习笔记——ST表

    作用: 给定一个数列 ai O(nlogn) 预处理 O(1) 查询区间最值 实现: 定义f(i,j) 为ai开始,包括ai的连续2^j个元素的最值 下面以最大值为例: f(i,j)表示max{ak} ...

  9. [tyvj-1391]走廊泼水节 最小生成树

    做克鲁斯卡尔的时候维护一个并查集即可. #include <iostream> #include <cstdio> #include <cstring> #incl ...

  10. ubuntu 下jrtplib编译

    我本来想用最新的 jrtplib-3.9.1和jthread-1.3.1,可是最新的那两个版本中都是用cmake进行配置的,我搞了好久,查了好多资料也没有解决交叉编译的问题,无奈,只能选用比较老的两个 ...