平衡二叉树(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. postgreSQL格式化时间的函数详解

    数据类型格式化函数:    PostgreSQL格式化函数提供一套有效的工具用于把各种数据类型(日期/时间.integer.floating point和numeric)转换成格式化的字符串以及反过来 ...

  2. 使用Storm实现实时大数据分析!

    随着数据体积的越来越大,实时处理成为了许多机构需要面对的首要挑战.Shruthi Kumar和Siddharth Patankar在Dr.Dobb's上结合了汽车超速监视,为我们演示了使用Storm进 ...

  3. Associated Values & enum

    it is sometimes useful to be able to store associated values of other types alongside these case val ...

  4. 执行opatch apply 报错 OPatch failed with error code 73

    .执行opatch apply 报错 OPatch failed [oracle@ora_11g 14275605]$ /opt/oracle/product/db_1/OPatch/opatch a ...

  5. IDEA 社区版 点击‘Edit Configurations’打开“Run/Debug Configurations”,里面没有tomcat server选项

    没错 社区版就是没有 “先手动添加Plugins 然后再setting” 方法无效 搜索不到 http://blog.csdn.net/u010666884/article/details/52119 ...

  6. python实现定时发送消息

    #!/usr/bin/env python#-*- coding:utf-8 -*- @Author : wujf @Time:2018/8/21 15:59# 自动发送消息from threadin ...

  7. php 常用header

    //定义编码 header( 'Content-Type:text/html;charset=utf-8 '); //Atom header('Content-type: application/at ...

  8. hdu 3177贪心

    #include<stdio.h>/*只能按这种形式排序单纯一种形式是不对的,按ai排序 20 2 1 1 10 20 按bi排序 20 2 5 17 1 16 都是不对的 二a.u+b. ...

  9. LCA【模板】

    #include <algorithm> #include <cstdio> #include <vector> #define N 10015 using nam ...

  10. HDU 4343

    二分加贪心,水过了.贪心是因为,不能存在覆盖,当存在覆盖时,留小坐标的. #include <iostream> #include <cstdio> #include < ...