红黑树与AVL树的区别

红黑树(Red Black Tree)

红黑树是一种自平衡二叉查找树,在插入和删除操作时通过特定操作(左旋、右旋)保持二叉查找树的平衡,从而获得较高的查找性能。

特征

  1. 节点是红色或黑色。
  2. 根节点是黑色。
  3. 所有叶子结点是黑色。
  4. 每个红色节点的两个子节点都是黑色。
  5. 从任一节结点到其每个叶子的所有路径都包含相同数目的黑色结点。

用途

  1. JDK1.8中HashMap使用数组+链表+红黑树的数据结构,当桶中长度超过8时从链表转为红黑树,当桶中长度小于6时从红黑树转为链表,提高检索效率。
  2. TreeMap也是基于红黑树的数据结构实现的,并且可以根据键值进行自然排序(也可以自定义排序)。
  3. Linux CFS 调度程序釆用高效算法(可运行的任务放置在红黑树上,基于vruntime)。
  4. IO多路复用select、poll、epoll机制中,epoll在执行epoll_create会在内核的高速缓存区中建立一颗红黑树以及就绪链表(就绪链表存储已经就绪的文件描述符fd),红黑树存放用户执行epoll_ctl函数添加的文件描述符fd。
  5. 其他... ...

原理

红黑树是一种高效查找的树,通过左旋右旋调整树的平衡,它的本质也是对概念模型:2-3-4树的一种实现。

2-3-4树在计算机科学中是阶为 4 的B树(Balance Tree),B树也叫平衡多路查找树。它最重要的特性在于平衡,这使得我们能够在最坏情况下也保持O(LogN)的时间复杂度实现查找。

先看B树中的2-3树2-3-4树的2节点结构:

红黑树与AVL树的区别_第1张图片

再看B树2-3树2-3-4树的3节点结构:

红黑树与AVL树的区别_第2张图片

再看B树2-3-4树的4节点结构:

红黑树与AVL树的区别_第3张图片 这里就会有个问题了,红黑树是从平衡树转换得到的,那么红黑树的染色和旋转的意义是什么?

  • 染色:红黑树的红色节点和黑色节点里,红黑或黑红表明的是一种父子关联关系。
  • 旋转:红黑树左旋和右旋是二叉树调整平衡的精髓。

红黑树插入删除操作如何调整可以在可视化网页上建一个红黑树:Red/Black Tree Visualization

下面通过一个例子去使用具有红黑树结构的TreeMap,一般不建议自定义的红黑树结构,避免留坑,下面的case记录经过坐标轴点的次数,

package com.hust.zhang.leetcode.tree;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.junit.platform.commons.util.StringUtils;

import java.util.Map;
import java.util.TreeMap;

public class DemoTest {
    private static Coordinate LOCATION = new Coordinate(0, 0);
    /**
     * 记录坐标点经过的次数,按距离坐标原点最近的坐标点进行排序
     */
    private static Map treeMap = new TreeMap<>(
            (o1, o2) -> (int) (Math.pow(o1.axis_x, 2) + Math.pow(o1.axis_y, 2) -
                    Math.pow(o2.axis_x, 2) - Math.pow(o2.axis_y, 2)));

    /**
     * 起始坐标点
     */
    static {
        treeMap.put(new Coordinate(LOCATION.axis_x, LOCATION.axis_y), 1);
    }

    @Data
    @AllArgsConstructor
    private static class Coordinate {
        private int axis_x;
        private int axis_y;
    }

    public static void main(String[] args) {
        String inputStr = "NESW";
        updateCoordinate(inputStr);
        treeMap.entrySet().forEach(System.out::println);
    }

    /**
     * 更新坐标轴记录
     *
     * @param inputStr 移动动作指令
     *                 'N' 代表NORTH—北
     *                 'S' 代表SOUTH-南
     *                 'W' 代表WEST——西
     *                 'E' 代表EAST——东
     */
    private static void updateCoordinate(String inputStr) {
        if (StringUtils.isBlank(inputStr)) {
            return;
        }
        for (int i = 0; i < inputStr.length(); i++) {
            if (inputStr.charAt(i) == 'N') {
                addLocationToMap(new Coordinate(LOCATION.axis_x, LOCATION.axis_y + 1));
                LOCATION.axis_y += 1;
            } else if (inputStr.charAt(i) == 'S') {
                addLocationToMap(new Coordinate(LOCATION.axis_x, LOCATION.axis_y - 1));
                LOCATION.axis_y -= 1;
            } else if (inputStr.charAt(i) == 'W') {
                addLocationToMap(new Coordinate(LOCATION.axis_x - 1, LOCATION.axis_y));
                LOCATION.axis_x -= 1;
            } else if (inputStr.charAt(i) == 'E') {
                addLocationToMap(new Coordinate(LOCATION.axis_x + 1, LOCATION.axis_y));
                LOCATION.axis_x += 1;
            }
        }
    }

    private static void addLocationToMap(Coordinate coordinate) {
        boolean flag = true;
        for (Map.Entry entry : treeMap.entrySet()) {
            Coordinate location = entry.getKey();
            if (location.axis_x == coordinate.axis_x && location.axis_y == coordinate.axis_y) {
                flag = false;
                treeMap.put(location, entry.getValue() + 1);
            }
        }
        if (flag) {
            treeMap.put(coordinate, 1);
        }
    }
}

AVL树(Self-Balancing Binary Search Tree,平衡二叉搜索树)

在计算机科学中,AVL树是最先发明的自平衡二叉查找树。

特征

  1. 典型的二叉搜索树(Balanced Search Binary Tree)。
  2. 在AVL树中任何节点的左右子树的高度之差的绝对值小于等于1。

用途

windows对进程地址空间进行管理,参看文末链接3。

原理

树的左右高度之差保证在「-1,0,1」,基于平衡性,查找的时间复杂度是O(logn)。树的平衡也是通过左旋和右旋进行维持。

插入删除时可能经过一次或多次左旋右旋,慢动作看数据结构可视化可以看到插入某一元素后,先调整高度,然后可能经过两次左旋。

下面直接看左旋右旋如何实现,

package com.hust.zhang.leetcode.tree;

/**
 * Self-Balancing Binary Search Tree,平衡二叉搜索树
 * 
 * 左右两个子树的高度差的绝对值不超过1
 */
public class AVLTree {
    private AVLTree(int val) {
        root = new TreeNode(val);
    }

    private TreeNode root;

    /**
     * 二叉树节点定义
     */
    private static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
            this.val = x;
        }
    }

    /**
     * 左旋操作
     * @param root 根节点
     * @return 一次左旋后的根节点
     *
     *                    A                                            C
     *                  /   \                                        /    \
     *                B      C             ——————>                  A      E
     *                     /   \                                  /   \
     *                    D     E                                B    D
     */
    private TreeNode leftRotation(TreeNode root) {
        TreeNode C = root.right;
        TreeNode D = C.left;
        // 左旋
        C.left = root;
        root.right = D;
        return C;
    }

    /**
     * 右旋操作
     * @param root 根节点
     * @return 一次右旋后的根节点
     *
     *                  A                                       B
     *                /   \                                  /     \
     *              B      C            ——————>             D       A
     *            /   \                                           /  \
     *           D    E                                          E    C
     *
     */
    private TreeNode rightRotation(TreeNode root) {
        TreeNode B = root.left;
        TreeNode E = B.right;
        // 右旋
        B.right = root;
        root.left = E;
        return B;
    }

    /**
     * 获取树的高度
     *
     * @param node 当前根节点
     * @return 树高
     */
    private int height(TreeNode node) {
        if (node == null) {
            return 0;
        }
        return Math.max(height(node.left), height(node.right)) + 1;
    }
}

主要区别

从上面可以了解到红黑树和AVL树都是平衡二叉树,具体的区别如下,

平衡二叉树类型 平衡度 调整频率 适用场景
AVL树 查询多,增/删少
红黑树 增/删频繁

参考链接:

1、CFS调度算法:http://c.biancheng.net/view/1255.html

2、数据结构可视化:Data Structure Visualization

3、Windows运用AVL树对进程地址空间的管理 - 开发者知识库

4、红黑树和AVL树的区别(转) - 奋斗终生 - 博客园

你可能感兴趣的:(笔记,数据结构)