往红黑树祖坟上刨根问底

介绍


正文


put

  • 说明
    • 在map 中插入key的节点 默认是不去重的,通过增加一个参数duplicate,true表示去重,因此方法签名为:public boolean put(boolean duplicate, int key, int value) ,
  • 设计思路
    • 第一步:找到插入节点的位置,并做插入操作(调整其父子节点的关系)
    • 第二步:进行颜色调整,颜色调整主要看 叔叔节点的颜色 和 父节点于祖父节点的位置
      • 红叔问题:更改叔叔节点、父节点、祖父节点颜色,并向上递归
      • 黑叔问题:涉及到左旋右旋及颜色调整
  • 主要源码
public boolean put(boolean duplicate, int key, int value) {
    if (initValue == this.root.key) {
        this.root.key = key;
        this.root.value = value;
        this.root.color = BLACK;
        this.size++;
        return true;
    }
    RedBlackNode point = new RedBlackNode(key, value);
    RedBlackNode search = this.root;
    RedBlackNode search_bef = this.root;
    while (search != null) {
        search_bef = search;
        if (duplicate && search.key == key) {
            //update
            search.value = value;
            return true;
        } else if (search.key < key) {
            search = search.right;
        } else {
            search = search.left;
        }
    }
    point.parent = search_bef;
    if (search_bef.key < key) {
        search_bef.right = point;
    } else {
        search_bef.left = point;
    }
    insertFixup(point);
    this.size++;
    return true;
}
//颜色调整
private void insertFixup(RedBlackNode point) {
    if (this.root == point.parent) {
        this.root.color = BLACK;
        return;
    }
    RedBlackNode uncle;
    while (null != point.parent && RED.equals(point.parent.color)) {
        uncle = (point.parent == point.parent.parent.left) ? point.parent.parent.right : point.parent.parent.left;
        if (null != uncle && RED.equals(uncle.color)) {
            //红叔问题
            uncle.color = BLACK;
            point.parent.color = BLACK;
            point.parent.parent.color = RED;
            point = point.parent.parent;
            if (this.root == point) {
                this.root.color = BLACK;
                return;
            }
            //红叔问题的最后一步是递归祖父节点,因为此处存在外循环,就省略递归操作
        } else {
            //黑叔问题
            if (uncle == point.parent.parent.right) {
                if (point == point.parent.right) {
                    rotateLeft(point.parent);
                    point = point.left;
                }
                point.parent.color = BLACK;
                point.parent.parent.color = RED;
                rotateRight(point.parent.parent);
            } else {
                if (point == point.parent.left) {
                    rotateRight(point.parent);
                    point = point.right;
                }
                point.parent.color = BLACK;
                point.parent.parent.color = RED;
                rotateLeft(point.parent.parent);
            }
        }
    }
}
//以右旋为例
private void rotateRight(RedBlackNode point) {
    RedBlackNode pleft = point.left;
    point.left = pleft.right;
    if (null != pleft.right) {
        pleft.right.parent = point;
    }
    pleft.parent = point.parent;
    if (null == point.parent) {
        this.root = pleft;
    } else if (point.parent.left == point) {
        point.parent.left = pleft;
    } else {
        point.parent.right = pleft;
    }
    pleft.right = point;
    point.parent = pleft;
}

remove

  • 说明
  • 设计思路
  • 主要源码

contain

  • 说明:查找key值是否存在于红黑树中。
  • 设计思路
    • 通过递归的思路,分别在左孩子和右孩子中查询值
  • 主要源码
public boolean contain(int key) {
    return contain(this.root, key);
}

private boolean contain(RedBlackNode node, int key) {
    if (node == null) {
        return false;
    }
    if (node.key == key) {
        return true;
    }
    if (key < node.key) {
        return contain(node.left, key);
    } else {
        return contain(node.right, key);
    }
}

get

  • 说明:根据Key值获取Value值
  • 设计思路
    • 通过递归的思路,分别在左孩子和右孩子中查询值,并返回
  • 主要源码
public int get(int key) {
    return get(this.root, key);
}

private int get(RedBlackNode node, int key) {
    if (node == null) {
        return keyNotFound;
    }
    if (node.key == key) {
        return node.value;
    }
    if (key < node.key) {
        return get(node.left, key);
    } else {
        return get(node.right, key);
    }
}

getBelowKey

  • 说明:获取map内比这个key值小的元素个数
  • 设计思路
    • 如果当前节点等于查询值,那么统计其左孩子的节点数量
    • 如果当前节点小于查询值,那么递归其右孩子节点,但是加上其左孩子的节点值,再加一(其节点本身)
    • 如果当前节点大于查询值,那么递归其左孩子节点
  • 主要源码
public int getBelowKey(int key) {
    if (!contain(key)) {
        return 0;
    }
    RedBlackNode root = this.root;
    int count = 0;
    while (root != null) {
        if (root.key == key) {
            return count + countNodeNum(root.left);
        } else if (root.key < key) {
            count = 1 + count + countNodeNum(root.left);
            root = root.right;
        } else {
            root = root.left;
        }
    }
    return 0;
}

private int countNodeNum(RedBlackNode node) {
    if (node == null) {
        return 0;
    }
    int count = countNodeNum(node.left) + countNodeNum(node.right) + 1;
    return count;
}

print

  • 说明
  • 设计思路
  • 主要源码
public void print(RedBlackNode root) {
    if (root == null) {
        return;
    }
    Queue<RedBlackNode> queue = new LinkedList<>();
    queue.offer(root);
    RedBlackNode front = root;
    RedBlackNode tail = root;
    while (!queue.isEmpty()) {
        RedBlackNode binaryTree = queue.poll();
        // System.out.print(binaryTree.value + " ");
        System.out.print(binaryTree.key + " ");
        if (binaryTree.left != null) {
            queue.offer(binaryTree.left);
            tail = binaryTree.left;
        }
        if (binaryTree.right != null) {
            queue.offer(binaryTree.right);
            tail = binaryTree.right;
        }
        if (binaryTree == front) {
            front = tail;
            System.out.println();
        }
    }
}

toarray

  • 说明:按照先序遍历的方式,输出红黑树
  • 设计思路
    • 通过中序递归的思路,分别获取左孩子和右孩子的值
  • 主要源码
public int[] toarray() {
    if (this.root.key == initValue) {
        return new int[]{};
    }
    this.red2array = new ArrayList<>();
    RedBlackTree2Array(this.root);
    int[] array = red2array.stream().mapToInt(Integer::intValue).toArray();
    return array;
}

private void RedBlackTree2Array(RedBlackNode node) {
    if (node == null) {
        return;
    }
    RedBlackTree2Array(node.left);
    this.red2array.add(node.key);
    RedBlackTree2Array(node.right);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值