AVL Tree Insertion

Overview

AVL tree is a special binary search tree, by definition, any node, its left tree height and right tree height difference is not more than 1. The purpose of AVL tree is to try best to reduce the search time complexity. if the binary search tree is too deep, that will increase the search cost. By converting it to AVL, the search time can be stably controlled within O(LogN).

Data Structure and High Level API

 

 public class AVLTreeNode
    {
        public int data
        {
            get;
            set;
        }

        public AVLTreeNode leftChild
        {
            get;
            set;
        }

        public AVLTreeNode rightChild
        {
            get;
            set;
        }

        public int height
        {
            get;
            set;
        }

        public AVLTreeNode(int data)
        {
            this.data = data;
            this.height = 1;
        }
    }

 

AVLTreeNode Insert(AVLTreeNode node, int key)

 

Recursion 

 

INParam: current root node, incoming key
OUT:       the new root node
AVLNode Insert(AVLTreeNode node, int key)
        = 
                1) if node is null, return new AVLNode(key)
                2) if key is greater than current node, node.rightChild = Insert(node.rightChild, key)
                3) if key is smaller than current node, node.leftChild = Insert(node.leftChild, key)

 

Source Code

 

   public class AVLTree
    {
        public AVLTreeNode root
        {
            get;
            set;
        }

        private int Height(AVLTreeNode node)
        {
            if (node == null)
            {
                return 0;
            }

            if (node.leftChild == null && node.rightChild == null)
            {
                return 1;
            }
            else if (node.leftChild == null)
            {
                return 1 + node.rightChild.height;
            }
            else if (node.rightChild == null)
            {
                return 1 + node.leftChild.height;
            }

            return 1 + Math.Max(node.leftChild.height, node.rightChild.height);
        }

        private int GetBalance(AVLTreeNode node)
        {
            if (node == null)
            {
                return 0;
            }

            return Height(node.leftChild) - Height(node.rightChild);
        }
      // 右旋,左孩子和右孙子
        private AVLTreeNode RightRotation(AVLTreeNode node)
        {
            AVLTreeNode childNode = node.leftChild;
            AVLTreeNode grandChildNode = childNode.rightChild;
            childNode.rightChild = node;
            node.leftChild = grandChildNode;

            // for affected nodes, update their height
            node.height = Math.Max(Height(node.leftChild), Height(node.rightChild)) + 1;
            childNode.height = Math.Max(Height(childNode.rightChild), Height(childNode.leftChild)) + 1;

            return childNode;
        }

    // 左旋
    // 右孩子和左孙子
private AVLTreeNode LeftRotation(AVLTreeNode node) { AVLTreeNode childNode = node.rightChild; AVLTreeNode grandChildNode = childNode.leftChild; childNode.leftChild = node; node.rightChild = grandChildNode; node.height = Math.Max(Height(node.leftChild), Height(node.rightChild)) + 1; childNode.height = Math.Max(Height(childNode.rightChild), Height(childNode.leftChild)) + 1; return childNode; } public AVLTreeNode Insert(AVLTreeNode node, int key) { if (node == null) { return new AVLTreeNode(key); } if (key < node.data) { node.leftChild = Insert(node.leftChild, key); } else { node.rightChild = Insert(node.rightChild, key); } node.height = 1 + Math.Max(Height(node.leftChild), Height(node.rightChild)); // after insertion, calculate the balance int balance = GetBalance(node); // left left case if (balance > 1 && node.leftChild.data > key) // balance is greater than 1, which means node must have left child. { // right rotation return RightRotation(node); // 向右转, 左左组合,入参是当前根节点, 要动谁,谁就是参数 } // left right case
        6
/
4
\
        5
if (balance > 1 && node.leftChild.data <= key) { // left rotation first node.leftChild = LeftRotation(node.leftChild); // 左旋,传入参数是左子节点 // then do right rotation return RightRotation(node); } // right right case if (balance < -1 && node.rightChild.data <= key) { // left rotation return LeftRotation(node); } // right left case if (balance < -1 && node.rightChild.data > key) { // right rotation node.rightChild = RightRotation(node.rightChild); // 右旋,传入参数是node rightChild // left rotation return LeftRotation(node); } return node; } public void InOrder(AVLTreeNode node) { if (node == null) { return; } InOrder(node.leftChild); Console.WriteLine(node.data); InOrder(node.rightChild); } }

 左旋和右旋分别cover两种情况,举个例子,右旋既可以解决左左的旋转,也可以解决右侧子树, 右左的情况。所以旋转函数只有两个API,左旋和右旋,no more choice!

转载于:https://www.cnblogs.com/xuyanran/p/8454750.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值