红黑树插入删除实例及动态UI过程

红黑树难点在与对插入及删除几种状态转换的理解。而理解最好的方法莫过于实测。在这里提供一个java实现及UI直观过程。

一,插入三种状态
1.叔叔节点也为红色
2.当前节点是右子和父节点是左子
3.当前节点和父节点都是左子且叔叔节点为空或黑
来一张算法导论上的图:
在这里插入图片描述
二、删除四种状态
1.兄弟节点为红色
2.兄弟节点为黑色且兄弟节点的子节点都为黑色
3.兄弟节点为黑色且兄弟节点的左节点为红,右节点为黑
4.兄弟节点为黑色且兄弟节点的右节点为红
再来一张算法导论上的图:
在这里插入图片描述
先上效果:
在这里插入图片描述
三、java实现

public class Rbtree {

	public static class Node {
		public Node(int value) {
			this.value = value;
			this.isRed = true;
		}

		public boolean isLeft() {
			return this.parent.left == this;
		}

		public boolean isRed;
		public Node parent;
		public Node left;
		public Node right;
		public int value;

		@Override
		public String toString() {
			return (isRed ? "red:" : "black:") + value + "";
		}
	}

	public static Node insert(Node root, Node node) {
		Node current = root;
		for (;;) {
			if (node.value > current.value) {
				if (current.right == null) {
					current.right = node;
					node.parent = current;
					break;
				}
				current = current.right;
			} else {
				if (current.left == null) {
					current.left = node;
					node.parent = current;
					break;
				}
				current = current.left;
			}
		}
		Node newRoot = fixInsert(node);
		if (newRoot != null) {
			root = newRoot;
		}
		return root;
	}

	private static Node fixInsert(Node node) {
		//根节点
		if (node.parent == null) {
			node.isRed = false;
			return node;
		}
		//父节点为黑直接结束
		if (node.isRed && !node.parent.isRed) {
			return null;
		}
		if (node.parent.parent == null) {
			node.parent.isRed = false;
			return null;
		}
		if (node.parent.isLeft()) {
			//叔叔节点也为红色
			if (node.parent.parent.right != null && node.parent.parent.right.isRed) {
				node.parent.isRed = false;
				node.parent.parent.right.isRed = false;
				node.parent.parent.isRed = true;
				return fixInsert(node.parent.parent);
			}
			//当前节点和父节点都是左子且叔叔节点为空或黑(为空就是叶子节点,所以同样认为是黑) 
			if (node.isLeft()
				&&(node.parent.parent.right == null || !node.parent.parent.right.isRed)) {
					node.parent.parent.isRed = true;
					node.parent.isRed = false;
					return rightRotate(node.parent.parent);
			//当前节点是右子和父节点是左子
			} else {
				leftRotate(node.parent);
				return fixInsert(node.left);
			}
		} else {
			//叔叔节点也为红色
			if (node.parent.parent.left != null && node.parent.parent.left.isRed) {
				node.parent.isRed = false;
				node.parent.parent.left.isRed = false;
				node.parent.parent.isRed = true;
				return fixInsert(node.parent.parent);
			}
			//当前节点和父节点都是右子且叔叔节点为空或黑(为空就是叶子节点,所以同样认为是黑) 
			if (!node.isLeft()
					&&(node.parent.parent.left == null || !node.parent.parent.left.isRed)) {
					node.parent.parent.isRed = true;
					node.parent.isRed = false;
					return leftRotate(node.parent.parent);
			//当前节点是左子和父节点是右子
			} else {
				rightRotate(node.parent);
				return fixInsert(node.right);
			}
		}
	}

	private static Node leftRotate(Node node) {
		if (node.right == null) {
			return null;
		}
		Node r = node.right;
		node.right = r.left;
		if (node.right != null) {
			node.right.parent = node;
		}

		Node p = node.parent;
		r.left = node;
		r.parent = p;
		if (r.parent != null) {
			if (node.isLeft()) {
				r.parent.left = r;
			} else {
				r.parent.right = r;
			}
		}
		node.parent = r;
		if (r.parent == null) {
			return r;
		} else {
			return null;
		}
	}

	private static Node rightRotate(Node node) {
		if (node.left == null) {
			return null;
		}
		Node l = node.left;
		node.left = l.right;
		if (node.left != null) {
			node.left.parent = node;
		}

		Node p = node.parent;
		l.right = node;
		l.parent = p;
		if (l.parent != null) {
			if (node.isLeft()) {
				l.parent.left = l;
			} else {
				l.parent.right = l;
			}
		}
		node.parent = l;
		if (l.parent == null) {
			return l;
		} else {
			return null;
		}
	}

	public static Node delete(Node root, Node node) {
		Node current = root;
		Node newRoot = null;
		for (;;) {
			if (current.value == node.value) {
				Node replace = findReplaceNode(current);
				if (replace != null) {
					current.value = replace.value;
					current = replace;
				}
				break;
			} else if (current.value < node.value) {
				if (current.right == null) {
					break;
				} else {
					current = current.right;
				}
			} else {
				if (current.left == null) {
					break;
				} else {
					current = current.left;
				}
			}

		}
		//替换节点只肯存在一个子节点
		//左子存在
		if (current.left != null) {
			//删除根节点
			if (current.parent == null) {
				newRoot = current.left;
				newRoot.parent = null;
			} else {
				current.value = current.left.value;
				//标识该节点需要删除
				current.left.value = Integer.MIN_VALUE;
				current = current.left;
			}
		//右子存在
		} else if (current.right != null) {
			//删除根节点
			if (current.parent == null) {
				newRoot = current.right;
				newRoot.parent = null;
			} else {
				current.value = current.right.value;
				current.right.value = Integer.MIN_VALUE;
				current = current.right;
			}
		} else {
			current.value = Integer.MIN_VALUE;
		}
		if (newRoot==null) {
			newRoot = fixDelete(current);
		}
		if (newRoot != null) {
			root = newRoot;
		}
		return root;
	}

	private static Node fixDelete(Node node) {
		//根节点
		if (node.parent == null) {
			//所有节点被删除返回空根
			if (node.value==Integer.MIN_VALUE) {
				return new Node(0);
			}else {
				node.isRed=false;
				return node;
			}
		}
		
		if (node.isRed) {
			//节点为红色时如果节点是被删除节点,直接删除
			if (node.value==Integer.MIN_VALUE) {
				deleteNode(node);
				return null;
			//如果不是则涂黑结束
			}else {
				node.isRed=false;
				return null;
			}
		}
		if (node.isLeft()) {
			//兄弟节点为红色
			if (node.parent.right.isRed) {
				node.parent.isRed = true;
				node.parent.right.isRed = false;
				Node a = leftRotate(node.parent);
				Node b = fixDelete(node);
				return b!=null?b:a;
			//兄弟节点为黑色且兄弟节点的子节点都为黑色(或空)
			} else if (!node.parent.right.isRed 
					&& (node.parent.right.left == null || !node.parent.right.left.isRed)
					&& (node.parent.right.right == null || !node.parent.right.right.isRed)) {
				node.parent.right.isRed = true;
				Node tmp = node.parent;
				deleteNode(node);
				return fixDelete(tmp);
			//兄弟节点为黑色且兄弟节点的左节点为红,右节点为黑(或空)	
			} else if (!node.parent.right.isRed
					&&(node.parent.right.left != null && node.parent.right.left.isRed)
					&& (node.parent.right.right == null || !node.parent.right.right.isRed)) {
				node.parent.right.left.isRed=false;
				node.parent.right.isRed=true;
				Node a = rightRotate(node.parent.right);
				Node b = fixDelete(node);
				return b!=null?b:a;
			//兄弟节点为黑色且兄弟节点的右节点为红
			}else if(!node.parent.right.isRed
					&& (node.parent.right.right != null && node.parent.right.right.isRed)) {
				node.parent.right.isRed=node.parent.isRed;
				node.parent.right.right.isRed=false;
				node.parent.isRed=false;
				Node tmp=node.parent;
				deleteNode(node);
				return leftRotate(tmp);
			}
		} else {
			//兄弟节点为红色
			if (node.parent.left.isRed) {
				node.parent.isRed = true;
				node.parent.left.isRed = false;
				Node a = rightRotate(node.parent);
				Node b = fixDelete(node);
				return b!=null?b:a;
			//兄弟节点为黑色且兄弟节点的子节点都为黑色(或空)
			} else if (!node.parent.left.isRed 
					&& (node.parent.left.left == null || !node.parent.left.left.isRed)
					&& (node.parent.left.right == null || !node.parent.left.right.isRed)) {
				node.parent.left.isRed = true;
				Node tmp = node.parent;
				deleteNode(node);
				return fixDelete(tmp);
			//兄弟节点为黑色且兄弟节点的右节点为红,左节点为黑(或空)	
			} else if (!node.parent.left.isRed
					&&(node.parent.left.left == null || !node.parent.left.left.isRed)
					&& (node.parent.left.right != null && node.parent.left.right.isRed)) {
				node.parent.left.left.isRed=false;
				node.parent.left.isRed=true;
				Node a = leftRotate(node.parent.left);
				Node b = fixDelete(node);
				return b!=null?b:a;
			//兄弟节点为黑色且兄弟节点的左节点为红
			}else if(!node.parent.left.isRed
					&& (node.parent.left.left != null && node.parent.left.left.isRed)) {
				node.parent.left.isRed=node.parent.isRed;
				node.parent.left.left.isRed=false;
				node.parent.isRed=false;
				Node tmp=node.parent;
				deleteNode(node);
				return leftRotate(tmp);
			}
		}
		return null;
	}

	private static void deleteNode(Node node) {
		if (node.value == Integer.MIN_VALUE) {
			if (node.isLeft()) {
				node.parent.left = null;
			} else {
				node.parent.right = null;
			}
			node.parent = null;
		}
	}

	private static Node findReplaceNode(Node del) {
		Node result = null;
		if ((result = del.left) != null) {
			while (result.right != null) {
				result = result.right;
			}
		} else if ((result = del.right) != null) {
			while (result.left != null) {
				result = result.left;
			}
		}
		return result;
	}

}

四、动态UI过程java实现

import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.util.Random;

import javax.swing.JFrame;

import com.bc.Rbtree.Node;
	


	public class DrawTree {

		private static Node root;
		
	    public static void main(String[] args) throws InterruptedException {
	    	Random random = new Random();
	    	Draw draw= new Draw();
	    	root = new Node(50);
	    	draw.paintNodes(root);
	    	for (int i = 0; i < 20; i++) {
				root= Rbtree.insert(root, new Node(i));
				Thread.sleep(1000);
				draw.paintNodes(root);
			}
	    	for (int i = 0; i < 10; i++) {
				root= Rbtree.delete(root, new Node(i));
				Thread.sleep(1000);
				draw.paintNodes(root);
				System.out.println(i);
			}
	    	draw.paintNodes(root);

	        
	    }
	}

	class Draw extends JFrame {

		private static final long serialVersionUID = 1L;
		private static final int w = 1200;
	    private static final int h = 600;
	    private static final int ply = 50;
	    private static final int begin = 50;


	    private Graphics jg;



	    private Color rectColor = new Color(0xf5f5f5);

	    public Draw() {
	        Container p = getContentPane();
	        setBounds(50, 50, w, h);
	        setVisible(true);
	        p.setBackground(rectColor);
	        setLayout(null);
	        setResizable(true);
	        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	        jg =  this.getGraphics();
	    }



	    public void paintNodes(Node node) {
	    	try {
        		Thread.sleep(100);
        		jg.clearRect(0, 0, w, h);
        		paintNode(node ,0,w ,begin);
        		Thread.sleep(100);
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	       
	    }
	    public void paintNode(Node node ,int xb,int xe ,int y) {
	    	if (node.isRed) {
	    		jg.setColor(Color.RED);
			}else {
				jg.setColor(Color.BLACK);
			}
	    	int x=xb+(xe-xb)/2;
	    	jg.drawOval(x, y, 20, 20);
	    	jg.setColor(Color.BLACK);
	    	jg.drawString(node.value+"", x+2, y+15);
	    	if (node.left!=null) {
	    		jg.drawLine(x, y, xb+(x-xb)/2, y+ply);
	    		paintNode( node.left, xb, x, y+ply);
			}
	    	if (node.right!=null) {
	    		jg.drawLine(x, y, x+(xe-x)/2, y+ply);
	    		paintNode( node.right, x, xe, y+ply);
			}
	    	
	    }

	
}

----完工----

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值