zoukankan      html  css  js  c++  java
  • AVL树(自平衡二叉查找树)

    了解AVL树之前要先了解二叉查找树(BST),BST查找元素的时间复杂度平均是O(logN),最坏的情况是O(N),所有的元素都接在左子树(或者右子树)就相当于一串链表了。而AVL树会对子树过高的情况进行优化,这里有个平衡因子的概念,当前节点的平衡因子=左子树高度-右子树高度,AVL树的每一个节点的平衡因子的绝对值都是 < 2 的。

    当一个新节点插入AVL树 ( 根节点为tree ) 的时候会有四种情况:

    假设距离新节点最近的失衡节点为 t ( 的平衡因子的绝对值达到了2,且距离新节点最近)

    1、LL型:新节点在 t1 的左孩子的左子树上,需要对 t 进行一次右旋操作;

    2、RR型:新节点在 t 的右孩子的右子树上,需要对 t 进行一次左旋操作;

    3、LR型:新节点在 t 的左孩子的右子树上,需要先对 t 的左孩子进行一次RR(左旋)操作,然后对 t 进行一次LL(右旋)操作;

    4、RL型:新节点在 t 的右孩子的左子树上,需要先对 t 的右孩子进行一次LL(右旋)操作,然后对 t 进行一次RR(左旋)操作;

    AVL树的实现代码如下:

      1 #include "pch.h"
      2 #include <iostream>
      3 #include <queue>
      4 #define ElementType int//自定义元素类型
      5 using namespace std;
      6 typedef struct node *AVLTree;
      7 struct node {
      8     ElementType key;
      9     int Height = 0;
     10     AVLTree left = NULL, right = NULL;
     11 };
     12 int Height(AVLTree tree);//求树的高度
     13 ElementType Max(ElementType a, ElementType b);
     14 AVLTree insert(AVLTree tree, ElementType &key);//在AVLTree中插入节点
     15 AVLTree LL_Rotation(AVLTree tree);//LL旋转
     16 AVLTree RR_Rotation(AVLTree tree);//RR旋转
     17 AVLTree LR_Rotation(AVLTree tree);//LR旋转
     18 AVLTree RL_Rotation(AVLTree tree);//RL旋转
     19 
     20 void levelTraversal(AVLTree tree);//层序遍历,用于测试
     21 
     22 /*用main函数来测试,给N个不同的数据,插入AVL树中,然后层序输出*/
     23 int main()
     24 {
     25     int N;
     26     ElementType key;
     27     AVLTree tree = NULL;
     28     scanf("%d", &N);
     29     for (int i = 0; i < N; i++) {
     30         cin >> key;
     31         tree = insert(tree, key);
     32     }
     33     levelTraversal(tree);
     34 }
     35 
     36 AVLTree insert(AVLTree tree, ElementType &key) {
     37     if (tree == NULL) {
     38         tree = new node();
     39         tree->key = key;
     40     }
     41     else if (key < tree->key) {
     42         tree->left = insert(tree->left, key);//key小于当前节点的值时继续往其左子树递归地插入
     43         if (Height(tree->left) - Height(tree->right) >= 2) {//左子树与右子树的高度差达到2的时候就要对当前节点进行旋转,这里由于是递归地执行,保证了平衡因子达到2的节点是最接近插入点的
     44             if (key < tree->left->key)
     45                 tree = LL_Rotation(tree);
     46             else
     47                 tree = LR_Rotation(tree);
     48         }
     49     }
     50     else {
     51         tree->right = insert(tree->right, key);
     52         if (Height(tree->right) - Height(tree->left) >= 2) {
     53             if (key > tree->right->key)
     54                 tree = RR_Rotation(tree);
     55             else
     56                 tree = RL_Rotation(tree);
     57         }
     58     }
     59     tree->Height = Max(Height(tree->left), Height(tree->right)) + 1;//当前节点的高度为其最大子树的高度+1
     60     return tree;
     61 }
     62 
     63 AVLTree LR_Rotation(AVLTree tree) {
     64     tree->left = RR_Rotation(tree->left);
     65     return LL_Rotation(tree);
     66 }
     67 
     68 AVLTree RL_Rotation(AVLTree tree) {
     69     tree->right = LL_Rotation(tree->right);
     70     return RR_Rotation(tree);
     71 }
     72 
     73 AVLTree RR_Rotation(AVLTree tree) {
     74     AVLTree tree2 = tree->right;
     75     tree->right = tree2->left;
     76     tree2->left = tree;
     77     tree->Height = Max(Height(tree->left), Height(tree->right)) + 1;
     78     tree2->Height = Max(Height(tree2->right), tree->Height) + 1;
     79     return tree2;
     80 }
     81 
     82 AVLTree LL_Rotation(AVLTree tree) {
     83     AVLTree tree2 = tree->left;
     84     tree->left = tree2->right;
     85     tree2->right = tree;
     86     tree->Height = Max(Height(tree->left), Height(tree->right)) + 1;
     87     tree2->Height = Max(Height(tree->left), tree->Height) + 1;
     88     return tree2;
     89 }
     90 
     91 int Height(AVLTree tree) {
     92     if (tree == NULL)
     93         return 0;
     94     return tree->Height;
     95 }
     96 
     97 ElementType Max(ElementType a, ElementType b) {
     98     return a > b ? a : b;
     99 }
    100 
    101 void levelTraversal(AVLTree tree)
    102 {
    103     queue <AVLTree> Q;
    104     Q.push(tree);
    105     while (!Q.empty()) {
    106         AVLTree t = Q.front();
    107         Q.pop();
    108         cout << t->key << " ";
    109         if (t->left != NULL)
    110             Q.push(t->left);
    111         if (t->right != NULL) 
    112             Q.push(t->right);
    113     }
    114 }
  • 相关阅读:
    线程基础知识归纳
    并发编程情况下几个相应问题简介
    Spring Security的RBAC数据模型嵌入
    Mysql插入中文的字段内容时乱码的解决方法
    部分排序算法总结
    sendEmail 阿里云使用587端口
    linux服务器关闭ipv6 方法
    centos 6.8 安装git 报错
    强大的xargs
    nfs环境搭建报错clnt_create: RPC: Program not registered
  • 原文地址:https://www.cnblogs.com/yinhao-ing/p/10732866.html
Copyright © 2011-2022 走看看