平衡二叉树(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. js手机网络检测

    <!DOCTYPE HTML> <html lang="en"> <head> <meta charset=UTF-8"> ...

  2. es6学习 http://es6.ruanyifeng.com/

    基础学习   http://es6.ruanyifeng.com/  够了 1字符串 字符串的遍历器接口 for (let codePoint of 'foo') { console.log(code ...

  3. 僧多粥少?还原 OpenStack 的真实“钱景”

    原文链接:http://www.oschina.net/news/57994/openstack-income-analysis 451 Research发布了OpenStack的收入分析预测,指出O ...

  4. vue项目布局

    1.底部有分类布局 类似这种底部有分类的,点击四个tap分别道不同的页面这样的,每个页面都是一个路由,把底部作为一个组件在每一个页面中引入就行.组件就是公用的,能公用的就写成组件.如下 { path: ...

  5. php 单例模式与常驻服务

    运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收.也就是 说,PHP在语言级别上没有办法让某个对象常驻内存.在PHP中,所有的变量都是页面级的,无论是全局变量,还是类的静态成员,都会在 ...

  6. js实现图片上传预览功能,使用base64编码来实现

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  7. sklearn学习1----sklearn.SVM.SVC

    1.SVM有两种作用:分类和回归,分类是用SVC,回归用SVR. 2.SVC:(中文官网) 重点在svm.SVC(),fit(X,Y),以及SVC中的参数. 3.SVC参数: ①C,C是控制软间隔中的 ...

  8. Project Euler 8 Largest product in a series

    题意:寻找这 1000 个数中相邻 13 个数相乘积最大的值 思路:首先想到的是暴力,但是还可以利用之前记录过的数值,什么意思呢?即在计算 2 - 14 后,再计算 3 - 15 时完全可以利用之前计 ...

  9. nyoj27-水池数目【DFS】

    题目描述: 南阳理工学院校园里有一些小河和一些湖泊,现在,我们把它们通一看成水池,假设有一张我们学校的某处的地图,这个地图上仅标识了此处是否是水池,现在,你的任务来了,请用计算机算出该地图中共有几个水 ...

  10. maven引入jsp相关依赖

    <!--引入Servlet开始--> <dependency> <groupId>javax.servlet</groupId> <artifac ...