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;
            }
        }
    }
    
时间: 2024-07-30 13:39:05

AVL数的相关文章

51nod 1412 AVL数的种类(DP

题意给了n个节点的AVL数 问种类 树的深度不大 那么转移方程很明显了 dp[i][j]   代表的是节点为n深度为j的树的种类 k为左子树的节点个数 //dp[i][j+1] += dp[k][j]*dp[i-k-1][j];//dp[i][j+1] += 2*dp[k][j-1]*dp[i-k-1][j]; #include <stdio.h> #include <iostream> #include <algorithm> #include <string.

数据结构——AVL数

转自:http://www.cnblogs.com/skywang12345/p/3577479.html AVL树的介绍 AVL树是高度平衡的而二叉树.它的特点是:AVL树中任何节点的两个子树的高度最大差别为1. 上面的两张图片,左边的是AVL树,它的任何节点的两个子树的高度差别都<=1:而右边的不是AVL树,因为7的两颗子树的高度相差为2(以2为根节点的树的高度是3,而以8为根节点的树的高度是1). AVL树的Java实现 1. 节点 1.1 节点定义 public class AVLTre

AVL树非递归插入删除思路

AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增加和删除可能需要通过一次或多次树旋转来重新平衡这个树.AVL树得名于它的发明者G.M. Adelson-Velsky和E.M. Landis,他们在1962年的论文<An algorithm for the organization of information>中发表了它. 节点的平衡因子是它的左子树的高度减去它的右子树的

01-常见的面试题目-TCP

1.C++运算符优先级 qqq 2.无符号数与有符号数的计算 qqq 3.sizeof(struct)计算与sizeof(union) qqqq 4.C++之Lambda表达式 qqqq 5.常见的八种排序算法 实现原理 时间复杂度(平均.最坏.最好) 对相同数字是否有序 搜相关其他面经 6.所有的数据结构整理(动态规划.分治...) 整理 7.图的最短路径 整理 8.屏幕分布不同的点,怎么找最短的点 整理 9.怎么理解动态规划,相关题 整理 10.宏替换及宏相关知识 宏替换时先求出实参表达式的

数据结构--AVL树

AVL树是高度平衡的二叉搜索树,较搜索树而言降低了树的高度:时间复杂度减少了使其搜索起来更方便: 1.性质: (1)左子树和右子树高度之差绝对值不超过1: (2)树中每个左子树和右子树都必须为AVL树: (3)每一个节点都有一个平衡因子(-1,0,1:右子树-左子树) (4)遍历一个二叉搜索树可以得到一个递增的有序序列 2.结构: 平衡二叉树是对二叉搜索树(又称为二叉排序树)的一种改进.二叉搜索树有一个缺点就是,树的结构是无法预料的.任意性非常大.它仅仅与节点的值和插入的顺序有关系.往往得到的是

平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板【超详解】

平衡树初阶——AVL平衡二叉查找树 一.什么是二叉树 1. 什么是树. 计算机科学里面的树本质是一个树状图.树首先是一个有向无环图,由根节点指向子结点.但是不严格的说,我们也研究无向树.所谓无向树就是将有向树的所有边看成无向边形成的树状图.树是一种递归的数据结构,所以我们研究树也是按照递归的方式去研究的. 2.什么是二叉树. 我们给出二叉树的递归定义如下: (1)空树是一个二叉树. (2)单个节点是一个二叉树. (3)如果一棵树中,以它的左右子节点为根形成的子树都是二叉树,那么这棵树本身也是二叉

AVL树原理及实现(C语言实现以及Java语言实现)

欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. AVL定义 AVL树是一种改进版的搜索二叉树.对于一般的搜索二叉树而言,如果数据恰好是按照从小到大的顺序或者从大到小的顺序插入的,那么搜索二叉树就对退化成链表,这个时候查找,插入和删除的时间都会上升到O(n),而这对于海量数据而言,是我们无法忍受的.即使是一颗由完全随机的数据构造成的搜索二叉树,从统计角度去分析,在进行若甘次的插入和删除操作,这个搜索二叉树的高度也不能令人满意.这个

数据结构之AVL树

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 在前面的博文中,我们已经介绍了数据结构之二分查找树的相关知识,二分查找的提出主要是为了提高数据的查找效率.同一个元素集合可以对应不同的二分查找树BST,二分查找树的形态依赖于元素的插入顺序.同时我们也已经知道,如果将一个有序的数据集依次插入到二查找树中,此时二分查找树将退化为线性表,此时查找的时间复杂度为o(n).为了防止这一问题的出现,便有了平衡二叉树的存在价值.平衡二叉树从根本上将是为了防止出现斜二叉树的出现,从而进一步提高元素的查找效率,

数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构.    a.树是n(≥0)结点组成的有限集合.{N.沃恩}     (树是n(n≥1)个结点组成的有限集合.{D.E.Knuth})      在任意一棵非空树中:        ⑴有且仅有一个没有前驱的结点----根(root).        ⑵当n>1时,其余结点有且仅有一个直接前驱.         ⑶所有结