zoukankan      html  css  js  c++  java
  • 数据结构(三)实现AVL树

    AVL树的定义
    一种自平衡二叉查找树,中面向内存的数据结构。
    二叉搜索树T为AVL树的满足条件为:

    • T是空树
    • T若不是空树,则TL、TR都是AVL树,且|HL-HR| <= 1 (节点的左子树高度与节点的右子树高度差的绝对值小于等于1)

    说明

    AVL树的实现类为AVLTree继承自前篇中的二叉搜索树BTreeSort ,AVL树的节点类为AVLNode继承自二叉树节点类BTreeNode。

    实现代码

    AVL树节点定义

    public class AVLNode extends BTreeNode {
     
        public int height; // 树高
        public int balanceFactor; // 平衡因子
       
        public AVLNode(int key){
            super(key);
        }
    }

    AVL树实现类

    public class AVLTree extends BTreeSort {
     
        private BTreeNode root;
     
        // 计算树高
        public int height(BTreeNode root) {
            if (null == root) {
                return 0;
            }
    10          return ((AVLNode) root).height;
    11      }
    12   
    13      // 计算平衡因子
    14      public void UpdateBalanceFactor(BTreeNode root) {
    15          if (null == root) {
    16              return;
    17          }
    18          int left = height(root.left);
    19          int right = height(root.right);
    20          ((AVLNode) root).height = Math.max(left, right) + 1;
    21          ((AVLNode) root).balanceFactor = left - right;
    22      }
    23   
    24      // 左左类型 -- 右转
    25      public BTreeNode rotateRight(BTreeNode root) {
    26          if (null == root) {
    27              return root;
    28          }
    29          BTreeNode node = root.left;
    30          root.left = node.right;
    31          node.right = root;
    32          UpdateBalanceFactor(root);
    33          UpdateBalanceFactor(node);
    34          return node;
    35      }
    36   
    37      // 右右类型 -- 左转
    38      public BTreeNode rotateLeft(BTreeNode root) {
    39          if (null == root) {
    40              return root;
    41          }
    42          BTreeNode node = root.right;
    43          root.right = node.left;
    44          node.left = root;
    45          UpdateBalanceFactor(root);
    46          UpdateBalanceFactor(node);
    47          return node;
    48      }
    49   
    50      // 左右类型
    51      public BTreeNode rotateLeftRight(BTreeNode root) {
    52          if (null == root) {
    53              return root;
    54          }
    55          root.left = rotateLeft(root.left);
    56          return rotateRight(root);
    57      }
    58   
    59      // 右左类型
    60      public BTreeNode rotateRightLeft(BTreeNode root) {
    61          if (null == root) {
    62              return root;
    63          }
    64          root.right = rotateRight(root.right);
    65          return rotateLeft(root);
    66      }
    67   
    68      // 插入节点
    69      public void insert(int key) {
    70          if (null == root) {
    71              root = new AVLNode(key);
    72              return;
    73          }
    74          root = insert(root, key);
    75      }
    76   
    77      // 插入节点构造AVL树
    78      public BTreeNode insert(BTreeNode root, int key) {
    79          if (null == root) {
    80              root = new AVLNode(key);
    81              UpdateBalanceFactor(root);
    82              return root;
    83          }
    84          // 等于
    85          if (key == root.key) {
    86              return root;
    87          }
    88          // 大于 -- 向左
    89          if (root.key > key) {
    90              root.left = insert(root.left, key);
    91              UpdateBalanceFactor(root);
    92              // / - 
    93              if (((AVLNode) root).balanceFactor > 1) {
    94                  // / - 
    95                  if (((AVLNode) root.left).balanceFactor > 0) {
    96                      root = rotateRight(root);
    97                  } else {
    98                      root = rotateLeftRight(root);
    99                  }
    100              }
    101          }
    102          // 小于或等于 -- 向右
    103          else {
    104              root.right = insert(root.right, key);
    105              UpdateBalanceFactor(root);
    106              // / - 
    107              if (((AVLNode) root).balanceFactor < -1) {
    108                  // / - 
    109                  if (((AVLNode) root.right).balanceFactor < 0) {
    110                      root = rotateLeft(root);
    111                  } else {
    112                      root = rotateRightLeft(root);
    113                  }
    114              }
    115          }
    116          UpdateBalanceFactor(root);
    117          return root;
    118      }
    119   
    120      // 删除节点
    121      public BTreeNode delete(BTreeNode root, int key) {
    122          if (null == root) {
    123              return root;
    124          }
    125          // 找到需删除的节点
    126          if (root.key == key) {
    127              // 该节点左右子树都不空处理
    128              if (null != root.left && null != root.right) {
    129                  // 左边子树高度大于右子树高度,使用左子树中最大节点替换需要删除的节点
    130                  if (((AVLNode) root.left).height > ((AVLNode) root.right).height) {
    131                      BTreeNode node = max(root.left);
    132                      root.key = node.key;
    133                      root.left = delete(root.left,node.key);
    134                  } else {
    135                      // 使用右子树中最小节点替换需要删除的节点
    136                      BTreeNode node = min(root.right);
    137                      root.key = node.key;
    138                      root.left = delete(root.right,node.key);
    139                  }
    140              } else {
    141                  root = null != root.left ? root.left : root.right;
    142              }
    143              UpdateBalanceFactor(root);
    144              return root;
    145          }
    146          // 往左边查找删除节点
    147          else if (root.key > key) {
    148              root.left = delete(root.left, key);
    149              UpdateBalanceFactor(root);
    150              // 左子树变矮只有可能右子树高度大于等于左子树高度
    151              // 
    152              if (((AVLNode)root).balanceFactor < -1){
    153                  //  右右类型处理
    154                  if (((AVLNode)root.left).balanceFactor < 0){
    155                      root = rotateLeft(root);
    156                  }
    157                  else{
    158                      // 右左类型处理
    159                      root = rotateRightLeft(root);
    160                  }
    161              }
    162          }
    163          // 往右边查找删除节点
    164          else {
    165              root.right = delete(root.right, key);
    166              UpdateBalanceFactor(root);
    167              // 右子树变矮只有可能左子树高度大于等于右子树高度
    168              // /
    169              if (((AVLNode)root).balanceFactor > 1){
    170                  // / 左左类型
    171                  if (((AVLNode)root.left).balanceFactor > 0){
    172                      root = rotateRight(root);
    173                  }
    174                  else{
    175                      // 左右类型
    176                      root = rotateLeftRight(root);
    177                  }
    178              }
    179          }
    180          UpdateBalanceFactor(root);
    181          return root;
    182      }
    183     
    184      // 中顺遍历
    185      public void midTraversal(){
    186          this.midTraversal(root);
    187      }
    188     
    189      // 删除节点
    190      public void delete(int key) {
    191          this.delete(root, key);
    192      }
    193     
    194      public static void main(String[] args) {
    195          Integer[] nums = new Integer[] { 20, 12, 9, 11, 17, 19, 18, 25, 30, 23,
    196                  55, 35, 67, 81, 13 };
    197          System.out.println(Arrays.asList(nums));
    198          AVLTree avlTree = new AVLTree();
    199          for (Integer num:nums){
    200              avlTree.insert(num.intValue());
    201          }
    202          avlTree.delete(20);
    203          System.out.print("中序遍历:");
    204          avlTree.midTraversal();
    205          System.out.println();
    206      }
    207  }
  • 相关阅读:
    在SQL中删除重复记录
    SQL语句生成SQLServer数据字典
    还原数据库时出现的问题
    Active Server Pages 错误 'ASP 0201'
    VS.NET新建项目时出现“两者需要映射到相同的服务器位置”
    cs0016: 未能写入输出文件“c:\windows\microsoft.net\***.dll”错误处理
    Svchost.exe进程详解
    5y5.us
    C# 中返回星期的函数
    怎样用C#实现完整文档打印功能
  • 原文地址:https://www.cnblogs.com/jianyuan/p/5329958.html
Copyright © 2011-2022 走看看