思路
红黑树本质上是对于2-3-4B树在遵循平衡二叉树规则的二叉树实现,通过旋转和颜色保证树本身的查询深度,有这么几条规则。
所有节点或为红色或为黑色,根节点比为黑色
新插入的节点为红色,任意两个红色节点都被一个以上的黑色节点隔开
遵循平衡二叉树规则旋转,根节点颜色不随旋转发生变化
代码实现
参数构造
本节点info字段用于存值,进行插入时拿来做比较
left和right分别为左右子节点
isRed用于标记节点颜色,默认为红色,当新节点
private int info;
private Point left;
private Point right;
private boolean isRed=true;//用于标记颜色,非红即黑,默认为红色
插入方法
遵循平衡二叉树插入规则,左小右大向下传递,之后调用树平衡和颜色调整方法
//插入
public void add(Point p){
if(this.info>p.getInfo()){
if(this.left!=null){
this.left.add(p);
}else{
this.left = p;
}
}
if(this.info<p.getInfo()){
if(this.right!=null){
this.right.add(p);
}else{
this.right = p;
changeColor();
}
}
balance();//树平衡
changeColor();//颜色调整
}
删除方法
删除方法思路遵循2-3-4B树的删除规则,选取离删除节点最近的值取代当前节点,
表现在平衡二叉树的情况下则是,选取左子树的最底右子节点或右子树的最底左子节点至被删除节点处,继承颜色并取代该值,同时删除被取到的节点
//删除
public void remove(int num){
if(this.info>num){
this.left.remove(num);
}
if(this.info<num){
this.right.remove(num);
}
if(this.info==num){
if(this.getLeft()!=null){
this.info = this.getLeft().getClose();
this.delete(this.info);
}else{
this.info = this.getRight().info;
this.left = this.getRight().left;
this.right = this.getRight().right;
}
}
}
void delete(int num){
if(this.getRight().info==num){
this.setRight(null);
}else{
this.getRight().delete(num);
}
balance();//树平衡
changeColor();//颜色调整
}
int getClose(){
if(this.getRight()!=null){
return this.getRight().getClose();
}else{
return this.info;
}
}
树平衡
进行插入和删除操作之后需平衡左右子树
思路为获取左右子树深度,差值超过2之后进行平衡
在此处颜色不随节点位置旋转
private void balance(){
//如果其左子树长度高于右,则进行向右旋转
if(this.getLeftHight()-this.getRightHight()>1){
this.rightRotate();
return;
}
//如果其右子树长度高于左,则进行向左旋转
if(this.getRightHight()-this.getLeftHight()>1){
this.leftRotate();
return;
}
}
public int getLeftHight(){
if(this.getLeft()==null){
return 0;
}
return this.getLeft().getHight();
}
public int getRightHight(){
if(this.getRight()==null){
return 0;
}
return this.getRight().getHight();
}
public int getHight(){
if(this.getRight()==null && this.getLeft()==null){
return 1;
}else{
return Math.max(this.getLeft() == null ? 0 : this.getLeft().getHight(), this.getRight() == null ? 0 : this.getRight().getHight())+ 1;
}
}
//向左旋转
private void leftRotate() {
/**
* 当右节点仅有一个左子树时需将左节点和其右子树关系先调整
* 将左子节点的右子节点设置为左节点,将原来的左子节点设为新左子节点的左子节点
* 方便旋转
*/
Point newPoint;
if(this.getRight().getLeft()!=null && this.getRight().getRight()==null){
newPoint = this.getRight();
this.setRight(this.getRight().getLeft());
this.getRight().setRight(newPoint);
this.getRight().getRight().setLeft(null);
}
newPoint = new Point(this.info);
if(this.getLeft()!=null){
newPoint.setLeft(this.getLeft());
}
this.setLeft(newPoint);
this.setInfo(this.getRight().getInfo());
/**
* 右节点的左右子节点均存在时,将右节点的左节点设置为左节点的右子树,将右节点的右子树设定为根节点的右子树
*/
if(this.getRight().getLeft()!=null){
this.getLeft().setRight(this.getRight().getLeft());
}
this.setRight(this.getRight().getRight());
//此代码中实现的旋转仅为值的旋转,保证根节点为黑色
this.isRed=false;
}
//向右旋转
private void rightRotate() {
/**
* 当左节点仅有一个右子树点时需将左节点和其右子树关系先调整
*/
Point newPoint;
if(this.getLeft().getRight()!=null && this.getLeft().getLeft()==null){
newPoint = this.getLeft();
this.setLeft(this.getLeft().getRight());
this.getLeft().setLeft(newPoint);
this.getLeft().getLeft().setRight(null);
}
newPoint = new Point(this.info);
if(this.getRight()!=null){
newPoint.setRight(this.getRight());
}
this.setRight(newPoint);
this.setInfo(this.getLeft().getInfo());
/**
* 左节点的左右子节点均存在时,将左节点的右节点设置为右节点的左子树,将左节点的左子树设定为根节点的左子树
*/
if(this.getLeft().getRight()!=null){
this.getRight().setLeft(this.getLeft().getRight());
}
this.setLeft(this.getLeft().getLeft());
//此代码中实现的旋转仅为值的旋转,保证根节点为黑色
this.isRed=false;
}
颜色调整
此处关注节点为爷爷节点,检测子节点和孙子节点是否存在连续红色,若存在则将自身变红,将子节点变黑,此方法逐步递归向上,直至将红色传递至根节点,此时遵循根节点必为黑色的原则,将根节点设置为黑色
void changeColor(){
if(this.left!=null && this.left.left!=null){
if(this.left.isRed && this.left.left.isRed){
this.isRed = true;
this.left.isRed = false;
}
}
if(this.left!=null && this.left.right!=null){
}
if(this.left!=null && this.right.left!=null){
}
if(this.left!=null && this.right.right!=null){
}
if(this.right!=null && this.left.left!=null){
}
if(this.right!=null && this.left.right!=null){
}
if(this.right!=null && this.right.left!=null){
}
if(this.right!=null && this.right.right!=null){
}
//setRootColorBlack();
}
完整代码
没有细调,大家当伪码看吧
package ReadBlackTree;
public class Point {
private int info;
private Point left;
private Point right;
private boolean isRed=true;//用于标记颜色,非红即黑,默认为红色
public Point(int num){this.info = num;}
public int getInfo() {
return info;
}
public void setInfo(int info) {
this.info = info;
}
public Point getLeft() {
return left;
}
public void setLeft(Point left) {
this.left = left;
}
public Point getRight() {
return right;
}
public void setRight(Point right) {
this.right = right;
}
public boolean isRed() {
return isRed;
}
public void setRed(boolean red) {
isRed = red;
}
//删除
public void remove(int num){
if(this.info>num){
this.left.remove(num);
}
if(this.info<num){
this.right.remove(num);
}
if(this.info==num){
if(this.getLeft()!=null){
this.info = this.getLeft().getClose();
this.delete(this.info);
}else{
this.info = this.getRight().info;
this.left = this.getRight().left;
this.right = this.getRight().right;
}
}
}
void delete(int num){
if(this.getRight().info==num){
this.setRight(null);
}else{
this.getRight().delete(num);
}
balance();//树平衡
changeColor();//颜色调整
}
int getClose(){
if(this.getRight()!=null){
return this.getRight().getClose();
}else{
return this.info;
}
}
//插入
public void add(Point p){
if(this.info>p.getInfo()){
if(this.left!=null){
this.left.add(p);
}else{
this.left = p;
}
}
if(this.info<p.getInfo()){
if(this.right!=null){
this.right.add(p);
}else{
this.right = p;
changeColor();
}
}
balance();//树平衡
changeColor();//颜色调整
}
void changeColor(){
if(this.left!=null && this.left.left!=null){
if(this.left.isRed && this.left.left.isRed){
this.isRed = true;
this.left.isRed = false;
}
}
if(this.left!=null && this.left.right!=null){
}
if(this.left!=null && this.right.left!=null){
}
if(this.left!=null && this.right.right!=null){
}
if(this.right!=null && this.left.left!=null){
}
if(this.right!=null && this.left.right!=null){
}
if(this.right!=null && this.right.left!=null){
}
if(this.right!=null && this.right.right!=null){
}
//setRootColorBlack();
}
private void balance(){
//如果其左子树长度高于右,则进行向右旋转
if(this.getLeftHight()-this.getRightHight()>1){
this.rightRotate();
return;
}
//如果其右子树长度高于左,则进行向左旋转
if(this.getRightHight()-this.getLeftHight()>1){
this.leftRotate();
return;
}
}
public int getLeftHight(){
if(this.getLeft()==null){
return 0;
}
return this.getLeft().getHight();
}
public int getRightHight(){
if(this.getRight()==null){
return 0;
}
return this.getRight().getHight();
}
public int getHight(){
if(this.getRight()==null && this.getLeft()==null){
return 1;
}else{
return Math.max(this.getLeft() == null ? 0 : this.getLeft().getHight(), this.getRight() == null ? 0 : this.getRight().getHight())+ 1;
}
}
//向左旋转
private void leftRotate() {
/**
* 当右节点仅有一个左子树时需将左节点和其右子树关系先调整
* 将左子节点的右子节点设置为左节点,将原来的左子节点设为新左子节点的左子节点
* 方便旋转
*/
Point newPoint;
if(this.getRight().getLeft()!=null && this.getRight().getRight()==null){
newPoint = this.getRight();
this.setRight(this.getRight().getLeft());
this.getRight().setRight(newPoint);
this.getRight().getRight().setLeft(null);
}
newPoint = new Point(this.info);
if(this.getLeft()!=null){
newPoint.setLeft(this.getLeft());
}
this.setLeft(newPoint);
this.setInfo(this.getRight().getInfo());
/**
* 右节点的左右子节点均存在时,将右节点的左节点设置为左节点的右子树,将右节点的右子树设定为根节点的右子树
*/
if(this.getRight().getLeft()!=null){
this.getLeft().setRight(this.getRight().getLeft());
}
this.setRight(this.getRight().getRight());
//此代码中实现的旋转仅为值的旋转,保证根节点为黑色
this.isRed=false;
}
//向右旋转
private void rightRotate() {
/**
* 当左节点仅有一个右子树点时需将左节点和其右子树关系先调整
*/
Point newPoint;
if(this.getLeft().getRight()!=null && this.getLeft().getLeft()==null){
newPoint = this.getLeft();
this.setLeft(this.getLeft().getRight());
this.getLeft().setLeft(newPoint);
this.getLeft().getLeft().setRight(null);
}
newPoint = new Point(this.info);
if(this.getRight()!=null){
newPoint.setRight(this.getRight());
}
this.setRight(newPoint);
this.setInfo(this.getLeft().getInfo());
/**
* 左节点的左右子节点均存在时,将左节点的右节点设置为右节点的左子树,将左节点的左子树设定为根节点的左子树
*/
if(this.getLeft().getRight()!=null){
this.getRight().setLeft(this.getLeft().getRight());
}
this.setLeft(this.getLeft().getLeft());
//此代码中实现的旋转仅为值的旋转,保证根节点为黑色
this.isRed=false;
}
}