算法导论之第十三章-红黑树

算法导论相关的博客类似自己的笔记,如果想学习,最好还是看看别人的吧。
最底下有新的NodeAction代码
红黑树,就是二叉树上有红色节点和黑色节点。需要满足以下几个要求:
1、每个节点要么是红的,要么是黑的。
2、根节点是黑色的。
3、每个叶子节点都是null节点,黑色的。
4、从根节点往下走,到任一叶子节点,经历的黑色数要一致。
5、红节点的子节点必须要是黑色的。

满足以上几个要求之后,就保证这个二叉树不会过长,因为4、5的要求,保证最长路径比最短路径,不会差过2倍,对于查询而言是非常好的事情,查询时间就是O(lgn)。
但是要保证红黑树的要求,还是不简单的,先说插入。
插入:
插入相对简单。
1、父亲是黑色的:直接插入,节点设为红色,不会破坏5条限制。
2、父节点是红色的:判断叔节点,如果叔节点是红色的:将叔节点和父节点染成黑子,爷节点染成红色,把叶节点当成新节点进行插入判断。
3、父节点是红色、叔节点是黑色时:就是旋转后改色,具体如下:
1)如果父节点在爷节点左,本节点在父节点左,爷节点右旋,爷节点变成父节点子节点,现在把叶节点染红,父节点染黑。
2)如果父节点在叶节点左,本节点在父节点右,将父节点左旋,而此时结构和1)一致,进行1)之后的操作。
3)同1),4)同2),只是方向变化。
插入结束:展示部分代码。
左旋:

    public void leftRotate(Node node) {
		Node right = node.right;
		Node parnet = node.parent;
		Node rightLeft = right.left;
		if (parnet != null) {
			if (parnet.left == node) {
				parnet.left = right;
			} else {
				parnet.right = right;
			}
			right.parent = parnet;// 对接父节点和右节点
		} else {
			right.parent = null;
		}
		if (rightLeft != null) {
			rightLeft.parent = node;
		}
		node.right = rightLeft;// 对接右节点的左节点和本节点
		node.parent = right;
		right.left = node;// 换本节点和右节点的位置
	}

右旋:

    public void rightRotate(Node node) {
		Node left = node.left;
		Node parnet = node.parent;
		Node leftRight = left.right;
		if (parnet != null) {
			if (parnet.left == node) {
				parnet.left = left;
			} else {
				parnet.right = left;
			}
			left.parent = parnet;// 对接父节点和左节点
		} else {
			left.parent = null;
		}
		if (leftRight != null) {
			leftRight.parent = node;
		}
		node.left = leftRight;// 对接左节点的右节点和本节点
		node.parent = left;
		left.right = node;// 换本节点和左节点的位置
	}

插入1:

if (parent.isBlack()) {
	return;// 父节点是黑色,不需要改动
}

插入2:

			// 叔节点为红节点时
			// 父节点和叔节点变黑,爷节点变红
			// 爷节点进行相同操作
			parent.color = EnumColor.black.key;
			parBroNode.color = EnumColor.black.key;
			groudPNode.color = EnumColor.red.key;
			addRotate(groudPNode);

插入3:

		if (parBroNode.isBlack()) {
			// 叔节点为黑时
			if (node == parent.left) {
				// 节点是左节点
				if (groudPNode.left == parent) {
					// 如果父节点是左节点
					// 爷右旋
					this.rightRotate(groudPNode);
					parent.color = EnumColor.black.key;
					groudPNode.color = EnumColor.red.key;
				} else {
					// 如果父节点是右节点
					// 父右旋
					this.rightRotate(parent);
					// 爷左旋
					this.leftRotate(groudPNode);
					groudPNode.color = EnumColor.red.key;
					node.color = EnumColor.black.key;
				}
			} else {
				// 节点是右节点
				if (groudPNode.left == parent) {
					// 如果父节点是左节点
					// 父左旋
					this.leftRotate(parent);
					// 爷右旋
					this.rightRotate(groudPNode);
					groudPNode.color = EnumColor.red.key;
					node.color = EnumColor.black.key;
				} else {
					// 如果父节点是右节点
					// 爷右旋
					this.leftRotate(groudPNode);
					parent.color = EnumColor.black.key;
					groudPNode.color = EnumColor.red.key;
				}
			}
		}

删除:
删除相对复杂,首先删除的必须是没有双子节点的节点,现在设定是只有左子节点,而无右子节点,如果要删除的节点不满足,要进行调换操作,找到删除节点左子节点的最右值节点,将次节点值替换到删除位置后,二叉树大小依旧满足。
1、删除节点是红色的:直接删除,把子节点给父节点做子节点,不会破坏5项规则
2、删除节点是黑色的,则要判断兄弟节点
1)兄弟节点是红色的,此时父节点必然是黑色的,更换兄弟节点和父节点的颜色,向删除节点一侧转动,此时兄弟节点是曾经兄弟节点的子节点,所以必为黑色,进入一下循环。
2)兄弟节点是黑色时,判断兄弟节点的子节点,如果左侄节点和右侄节点都为黑色,把本节点和兄弟节点染红,父节点加一层黑色,如果父节点是黑的,则要网爷节点进行判断,这里有问题,我的判断太多,可以有修改之处。
3)兄弟节点是黑色、远侄节点[如本节点为左节点,在此侄节点为兄弟节点的右节点]为黑色(近侄节点)为红色时,更换远侄节点和兄弟节点的颜色,往远离删除节点的一侧选择,此时恰好是可能4)
4)兄弟节点是黑色、远侄节点为红色时,本节点删除、更换父节点和兄弟节点颜色,远侄节点染黑。

寻找替换节点的代码:

	public Node getBesideNode(Node node) {
		return getBestRight(node.left);
	}

	public Node getBestRight(Node node) {
		if (node.right.isNullNode()) {
			return node;
		}
		return getBestRight(node.right);
	}

删除1:

		if (node.isRed()) {
			//System.out.println("删除红节点");
			// 红节点必有父节点
			Node parent = node.parent;
			// 以下两个不可能都满足
			if (!node.left.isNullNode()) {
				//System.out.println("左节点给父节点做子节点");
				//System.out.println(parent.color);
				node.left.parent = parent;
				if (node == parent.left) {
					parent.left = node.left;
				} else {
					parent.right = node.left;
				}
			}else if (!node.right.isNullNode()) {
				//System.out.println("右节点给父节点做子节点");
				//System.out.println(parent.color);
				node.right.parent = parent;
				if (node == parent.left) {
					parent.left = node.right;
				} else {
					parent.right = node.right;
				}
			}else {
				/*Node top = this.getTopNode(node);
				if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
					System.out.println("删除前就错了");
				}*/
				//System.out.println("删除的没有子节点");
				//System.out.println(parent.color);
				if (node == parent.left) {
					parent.left = Node.nullNode(node, EnumColor.black.key);
				} else {
					parent.right = Node.nullNode(node, EnumColor.black.key);
				}
			}
			return;
		}

删除2 1):

		if (broNode.isRed()) {
			//System.out.println("兄弟为红时,父节点:"+parent.color);
			// 兄弟节点为红色时(父节点必为黑色)
			// 切换父节点和兄弟节点的肤色
			parent.color = EnumColor.red.key;
			broNode.color = EnumColor.black.key;
			// 进行旋转
			if (parent.left == node) {
				this.leftRotate(parent);
			} else {
				this.rightRotate(parent);
			}
			removeTrueBlackNode(node);
			//Node top = this.getTopNode(node);
			//this.checkNode(top);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
				//System.out.println("兄弟为红时 错了");
			//}
			return;
		}

删除2 2):

		// 当兄弟为黑色时
		if (broNode.left.isBlack() && broNode.right.isBlack()) {
			//Node top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
				//System.out.println("兄弟子弟都是黑色前就错了");
			//}
			//System.out.println("兄弟子弟都是黑色时"+broNode.color);
			// 当兄弟的子女都是黑色时
			node.color = EnumColor.red.key;
			broNode.color = EnumColor.red.key;
			this.setColorBlack(node.parent);
			//top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
				//System.out.println("兄弟子弟都是黑色时就错了");
			//}
			removeTrue(node);
			return;
		}

删除2 3):

		// 当当前节点是左节点,并且兄弟节点的右节点是黑色时
		if (node == parent.left && broNode.right.isBlack()) {
			//System.out.println("当当前节点是左节点,并且兄弟节点的右节点是黑色时");
			broNode.color = EnumColor.red.key;
			broNode.left.color = EnumColor.black.key;
			this.rightRotate(broNode);
			removeTrueBlackNode(node);
			//Node top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
			//}
			return;
		}
		// 当当前节点是右节点,并且兄弟节点的左节点是黑色时
		if (node == parent.right && broNode.left.isBlack()) {
			//System.out.println("当当前节点是右节点,并且兄弟节点的左节点是黑色时");
			broNode.color = EnumColor.red.key;
			broNode.right.color = EnumColor.black.key;
			this.leftRotate(broNode);
			removeTrueBlackNode(node);
			//Node top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
			//}
			return;
		}

删除2 4):

		// 当当前节点是左节点,并且兄弟节点的右节点是红色时
		if (node == parent.left && broNode.right.isRed()) {
			//System.out.println("当当前节点是左节点,并且兄弟节点的右节点是红色时");
			node.color = EnumColor.red.key;
			broNode.color = node.parent.color;
			node.parent.color = EnumColor.black.key;
			broNode.right.color = EnumColor.black.key;
			this.leftRotate(parent);
			removeTrue(node);
			//Node top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
			//}
			return;
		}
		// 当当前节点是右节点,并且兄弟节点的左节点是红色时
		if (node == parent.right && broNode.left.isRed()) {
			//System.out.println("当当前节点是右节点,并且兄弟节点的左节点是红色时");
			node.color = EnumColor.red.key;
			broNode.color =  node.parent.color;
			node.parent.color = EnumColor.black.key;
			broNode.left.color = EnumColor.black.key;
			this.rightRotate(parent);
			removeTrue(node);
			//Node top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
			//}
			return;
		}

完整代码:
测试类:

package test2019.mon01.红黑树;

import java.util.Random;

/**
 * Filename: Test.java Description: Company: sendinfo.com.cn Inc.
 * 
 * @author: guzhangyan
 * @date: 2019年1月29日 上午10:10:35
 */
public class Test {

	public static void main(String[] args) {
		NodeAction nodeAction = new NodeAction();
		Random random = new Random();

		Node top = Node.newNode(EnumColor.black.key, random.nextInt(1000));
		System.out.println("起始根节点:" + top.value);
		for (int i = 0; i < 1000; i++) {
			Node node = Node.newNode(EnumColor.red.key, random.nextInt(1000));
			nodeAction.addNode(top, node);
			top = nodeAction.getTopNode(top);
		}
		nodeAction.checkNode(top);// 校验二叉树是否成立
		System.out.println("最终根节点:" + top.value + ",根节点是:" + EnumColor.getColorValue(top.color));
		// 校验最长路径和最短路径是否有相差两倍
		System.out.println("最短路径:" + nodeAction.getMinLength(top));
		System.out.println("最长路径:" + nodeAction.getMaxLength(top));
		System.out.println("最短黑色路径:" + nodeAction.getMinBlackLength(top));
		System.out.println("最长黑色路径:" + nodeAction.getMaxBlackLength(top));
		System.out.println("剩余数值:"+nodeAction.getNodeSum(top));
		System.out.println("剩余数目:"+nodeAction.getNodeSumNumber(top));

		int num = nodeAction.getNodeSum(top);
		int number = nodeAction.getNodeSumNumber(top);
		String numStr = "";
		for (int j = 0; j < 3; j++) {
			numStr = "";
			for (int i = 0; i < 1000; i++) {
				nodeAction.checkNode(top);
				// System.out.println("真错了");
				nodeAction.remove(top, i);
				System.out.println("删除了:"+i);
				top = nodeAction.getTopNode(top);
				int newNumber = nodeAction.getNodeSumNumber(top);
				if(number!=newNumber) {
					System.out.println("扣除"+(number-newNumber)+"次");
					if(number-newNumber!=1) {
						System.out.println("有问题");
						nodeAction.printAllLeft(top);
					}
					number=newNumber;
					numStr += i+",";
				}
				int newNum = nodeAction.getNodeSum(top);
				if(num!=newNum) {
					System.out.println("扣除数字为:"+(num-newNum));
					num=newNum;
				}
				if (nodeAction.getMinBlackLength(top) != nodeAction.getMaxBlackLength(top)) {
					System.out.println("已经错了");
					System.out.println("最短黑色路径:" + nodeAction.getMinBlackLength(top));
					System.out.println("最长黑色路径:" + nodeAction.getMaxBlackLength(top));
					return;
				}
			}
			System.out.println("本次删除:"+numStr);
		}
		nodeAction.checkNode(top);// 校验二叉树是否成立
		System.out.println("最终根节点:" + top.value + ",根节点是:" + EnumColor.getColorValue(top.color));
		// 校验最长路径和最短路径是否有相差两倍
		System.out.println("最短路径:" + nodeAction.getMinLength(top));
		System.out.println("最长路径:" + nodeAction.getMaxLength(top));
		System.out.println("最短黑色路径:" + nodeAction.getMinBlackLength(top));
		System.out.println("最长黑色路径:" + nodeAction.getMaxBlackLength(top));
		System.out.println("剩余数值:"+nodeAction.getNodeSum(top));
		System.out.println("剩余数目:"+nodeAction.getNodeSumNumber(top));
		System.out.println("左遍历:");
		nodeAction.printAllLeft(top);
		System.out.println();
		System.out.println("右遍历:");
		nodeAction.printAllRight(top);
	}
}

Node类:

package test2019.mon01.红黑树;

/**
 * Filename: Node.java Description:
 * 
 * @author: guzhangyan
 * @date: 2019年1月29日 上午9:55:46
 */
public class Node {

	public Node(Node left, Node right, Node parent, int color, Integer value) {
		super();
		this.left = left;
		this.right = right;
		this.parent = parent;
		this.color = color;
		this.value = value;
	}

	public Node() {
	}

	public Node left;
	public Node right;
	public Node parent;
	public int color;// 0红色1黑色
	public Integer value;

	public boolean isBlack() {
		return color == EnumColor.black.key;
	}

	public static Node nullNode(Node parent, int key) {
		return new Node(null, null, parent, key, null);
	}

	public static Node newNode(int key, int value) {
		Node node = new Node(null, null, null, key, value);
		node.left = nullNode(node, EnumColor.black.key);
		node.right = nullNode(node, EnumColor.black.key);
		return node;
	}

	public boolean isNullNode() {
		return value == null;
	}

	public Node Brother() {
		Node parent = this.parent;
		if(parent==null) {
			System.out.println("父节点不存在,所以也没有兄弟节点");
		}
		Node broNode = parent.left;
		if(broNode == this) {
			broNode = parent.right;
		}
		return broNode;
	}

	public boolean isRed() {
		return !isBlack();
	}

	public static Node copyOf(Node node) {
		return new Node(node.left,node.right,node.parent,node.color,node.value);
	}

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

	public void copyOfOld(Node node) {
		this.left = node.left;
		this.right = node.right;
		this.parent = node.parent;
		this.value = node.value;
		this.color = node.color;
	}
}

NodeAction:

package test2019.mon01.红黑树;

/**
 * Filename: NodeAction.java Description:
 * 
 * @author: guzhangyan
 * @date: 2019年1月29日 上午9:57:39
 */
public class NodeAction {

	public void rightRotate(Node node) {
		Node left = node.left;
		Node parnet = node.parent;
		Node leftRight = left.right;
		if (parnet != null) {
			if (parnet.left == node) {
				parnet.left = left;
			} else {
				parnet.right = left;
			}
			left.parent = parnet;// 对接父节点和左节点
		} else {
			left.parent = null;
		}
		if (leftRight != null) {
			leftRight.parent = node;
		}
		node.left = leftRight;// 对接左节点的右节点和本节点
		node.parent = left;
		left.right = node;// 换本节点和左节点的位置
	}

	public void leftRotate(Node node) {
		Node right = node.right;
		Node parnet = node.parent;
		Node rightLeft = right.left;
		if (parnet != null) {
			if (parnet.left == node) {
				parnet.left = right;
			} else {
				parnet.right = right;
			}
			right.parent = parnet;// 对接父节点和右节点
		} else {
			right.parent = null;
		}
		if (rightLeft != null) {
			rightLeft.parent = node;
		}
		node.right = rightLeft;// 对接右节点的左节点和本节点
		node.parent = right;
		right.left = node;// 换本节点和右节点的位置
	}

	public void addLeftNode(Node parent, Node node) {
		parent.left = node;
		node.parent = parent;
		node.left = Node.nullNode(node, EnumColor.black.key);
		node.right = Node.nullNode(node, EnumColor.black.key);
		node.color = EnumColor.red.key;
		addRotate(node);
	}

	public void addRightNode(Node parent, Node node) {
		parent.right = node;
		node.parent = parent;
		node.left = Node.nullNode(node, EnumColor.black.key);
		node.right = Node.nullNode(node, EnumColor.black.key);
		node.color = EnumColor.red.key;
		addRotate(node);
	}

	// 添加之后旋转
	public void addRotate(Node node) {
		Node parent = node.parent;
		if (parent == null) {
			node.color = EnumColor.black.key;
			return;
		}
		if (parent.isBlack()) {
			return;// 父节点是黑色,不需要改动
		}
		// 当父节点是红色时,判断叔节点的颜色
		Node groudPNode = parent.parent;// 爷节点
		if (groudPNode == null) {
			parent.color = EnumColor.black.key;
			return;// 爷节点不存在时,结束
		}
		Node parBroNode = groudPNode.left;
		if (groudPNode.left == parent) {
			parBroNode = groudPNode.right;
		}
		if (parBroNode.isBlack()) {
			// 叔节点为黑时
			if (node == parent.left) {
				// 节点是左节点
				if (groudPNode.left == parent) {
					// 如果父节点是左节点
					// 爷右旋
					this.rightRotate(groudPNode);
					parent.color = EnumColor.black.key;
					groudPNode.color = EnumColor.red.key;
				} else {
					// 如果父节点是右节点
					// 父右旋
					this.rightRotate(parent);
					// 爷左旋
					this.leftRotate(groudPNode);
					groudPNode.color = EnumColor.red.key;
					node.color = EnumColor.black.key;
				}
			} else {
				// 节点是右节点
				if (groudPNode.left == parent) {
					// 如果父节点是左节点
					// 父左旋
					this.leftRotate(parent);
					// 爷右旋
					this.rightRotate(groudPNode);
					groudPNode.color = EnumColor.red.key;
					node.color = EnumColor.black.key;
				} else {
					// 如果父节点是右节点
					// 爷右旋
					this.leftRotate(groudPNode);
					parent.color = EnumColor.black.key;
					groudPNode.color = EnumColor.red.key;
				}
			}
		} else {
			// 叔节点为红节点时
			// 父节点和叔节点变黑,爷节点变红
			// 爷节点进行相同操作
			parent.color = EnumColor.black.key;
			parBroNode.color = EnumColor.black.key;
			groudPNode.color = EnumColor.red.key;
			addRotate(groudPNode);
		}
	}

	public void addNode(Node parent, Node node) {
		if (parent.value > node.value) {
			if (parent.left.isNullNode()) {
				this.addLeftNode(parent, node);
			} else {
				addNode(parent.left, node);
			}
		} else {
			if (parent.right.isNullNode()) {
				this.addRightNode(parent, node);
			} else {
				addNode(parent.right, node);
			}
		}
	}

	public Node getTopNode(Node node) {
		Node top = node;
		while (top.parent != null) {
			top = top.parent;
		}
		return top;
	}

	public int getMinLength(Node node) {
		if (node.isNullNode()) {
			return 0;
		}
		int leftlength = getMinLength(node.left);
		int rightlength = getMinLength(node.right);
		return (leftlength > rightlength ? rightlength : leftlength) + 1;
	}

	public int getMaxLength(Node node) {
		if (node.isNullNode()) {
			return 0;
		}
		int leftlength = getMaxLength(node.left);
		int rightlength = getMaxLength(node.right);
		return (leftlength < rightlength ? rightlength : leftlength) + 1;
	}

	public void checkNode(Node node) {
		if (!node.left.isNullNode()) {
			if (node.left.value > node.value) {
				System.out.println("出错了");
				return;
			}
			if(node.isRed()) {
				if(node.left.isRed()) {
					System.out.println("左双红:"+node.value+":"+node.left.value);
					//System.out.println(this.getTopNode(node).value);
					return;
				}
			}
			this.checkNode(node.left);
		}
		if (!node.right.isNullNode()) {
			if (node.right.value < node.value) {
				System.out.println("出错了");
				return;
			}
			if(node.isRed()) {
				if(node.right.isRed()) {
					System.out.println("右双红:"+node.value+":"+node.right.value);
					//System.out.println(this.getTopNode(node).value);
					return;
				}
			}
			this.checkNode(node.right);
		}
	}

	public int getMinBlackLength(Node node) {
		if (node.isNullNode()) {
			return 0;
		}
		int leftlength = getMinBlackLength(node.left);
		int rightlength = getMinBlackLength(node.right);
		return (leftlength > rightlength ? rightlength : leftlength) + (node.isBlack() ? 1 : 0);
	}

	public int getMaxBlackLength(Node node) {
		if (node.isNullNode()) {
			return 0;
		}
		int leftlength = getMaxBlackLength(node.left);
		int rightlength = getMaxBlackLength(node.right);
		return (leftlength < rightlength ? rightlength : leftlength) + (node.isBlack() ? 1 : 0);
	}

	public void remove(Node node, int value) {
		if (node.value.equals(value)) {
			remove(node);
			return;
		}
		if (node.value - value > 0) {
			if (!node.left.isNullNode()) {
				remove(node.left, value);
			}
		} else {
			if (!node.right.isNullNode()) {
				remove(node.right, value);
			}
		}
	}

	public void remove(Node node) {
		//System.out.println("开始删除:"+node.value);
		if ((!node.left.isNullNode()) && (!node.right.isNullNode())) {
			// 当节点左右节点都在时
			Node besideNode = getBesideNode(node);
			node.value = besideNode.value;
			removeTrue(besideNode);
			return;
		}
		removeTrue(node);
	}

	public Node getBesideNode(Node node) {
		return getBestRight(node.left);
	}

	public Node getBestRight(Node node) {
		if (node.right.isNullNode()) {
			return node;
		}
		return getBestRight(node.right);
	}

	public void change(Node node, Node besideNode) {
		Node newNode = Node.copyOf(node);
		node = Node.copyOf(besideNode);
		besideNode = Node.copyOf(newNode);
		int value = node.value;
		node.value = besideNode.value;
		besideNode.value = value;
	}

	public void removeTrue(Node node) {
		if (node.isRed()) {
			//System.out.println("删除红节点");
			// 红节点必有父节点
			Node parent = node.parent;
			// 以下两个不可能都满足
			if (!node.left.isNullNode()) {
				//System.out.println("左节点给父节点做子节点");
				//System.out.println(parent.color);
				node.left.parent = parent;
				if (node == parent.left) {
					parent.left = node.left;
				} else {
					parent.right = node.left;
				}
			}else if (!node.right.isNullNode()) {
				//System.out.println("右节点给父节点做子节点");
				//System.out.println(parent.color);
				node.right.parent = parent;
				if (node == parent.left) {
					parent.left = node.right;
				} else {
					parent.right = node.right;
				}
			}else {
				/*Node top = this.getTopNode(node);
				if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
					System.out.println("删除前就错了");
				}*/
				//System.out.println("删除的没有子节点");
				//System.out.println(parent.color);
				if (node == parent.left) {
					parent.left = Node.nullNode(node, EnumColor.black.key);
				} else {
					parent.right = Node.nullNode(node, EnumColor.black.key);
				}
			}
			return;
		}
		// 当节点是黑色时
		// 当不存在父节点时
		//System.out.println("黑色");
		if (node.parent == null) {
			System.out.println("我是根节点");
			if (!node.left.isNullNode()) {
				node.copyOfOld(node.left);
				node.parent = null;
				node.color = EnumColor.black.key;
				return;
			}
			if (!node.right.isNullNode()) {
				node.copyOfOld(node.right);
				node.parent = null;
				node.color = EnumColor.black.key;
				return;
			}
			System.out.println("我是最后一个了,不知道怎么删除了");
			return;
		}
		this.removeTrueBlackNode(node);
	}

	public void removeTrueBlackNode(Node node) {
		//System.out.println("删除黑节点");
		// 如果有父节点,而本节点是黑色,所以必有兄弟节点
		Node parent = node.parent;
		Node broNode = node.Brother();
		if (broNode.isRed()) {
			//System.out.println("兄弟为红时,父节点:"+parent.color);
			// 兄弟节点为红色时(父节点必为黑色)
			// 切换父节点和兄弟节点的肤色
			parent.color = EnumColor.red.key;
			broNode.color = EnumColor.black.key;
			// 进行旋转
			if (parent.left == node) {
				this.leftRotate(parent);
			} else {
				this.rightRotate(parent);
			}
			removeTrueBlackNode(node);
			//Node top = this.getTopNode(node);
			//this.checkNode(top);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
				//System.out.println("兄弟为红时 错了");
			//}
			return;
		}
		// 当兄弟为黑色时
		if (broNode.left.isBlack() && broNode.right.isBlack()) {
			//Node top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
				//System.out.println("兄弟子弟都是黑色前就错了");
			//}
			//System.out.println("兄弟子弟都是黑色时"+broNode.color);
			// 当兄弟的子女都是黑色时
			node.color = EnumColor.red.key;
			broNode.color = EnumColor.red.key;
			this.setColorBlack(node.parent);
			//top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
				//System.out.println("兄弟子弟都是黑色时就错了");
			//}
			removeTrue(node);
			return;
		}
		// 当兄弟的子女不都是黑色时
		// 当当前节点是左节点,并且兄弟节点的右节点是黑色时
		if (node == parent.left && broNode.right.isBlack()) {
			//System.out.println("当当前节点是左节点,并且兄弟节点的右节点是黑色时");
			broNode.color = EnumColor.red.key;
			broNode.left.color = EnumColor.black.key;
			this.rightRotate(broNode);
			removeTrueBlackNode(node);
			//Node top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
			//}
			return;
		}
		// 当当前节点是右节点,并且兄弟节点的左节点是黑色时
		if (node == parent.right && broNode.left.isBlack()) {
			//System.out.println("当当前节点是右节点,并且兄弟节点的左节点是黑色时");
			broNode.color = EnumColor.red.key;
			broNode.right.color = EnumColor.black.key;
			this.leftRotate(broNode);
			removeTrueBlackNode(node);
			//Node top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
			//}
			return;
		}
		// 当当前节点是左节点,并且兄弟节点的右节点是红色时
		if (node == parent.left && broNode.right.isRed()) {
			//System.out.println("当当前节点是左节点,并且兄弟节点的右节点是红色时");
			node.color = EnumColor.red.key;
			broNode.color = node.parent.color;
			node.parent.color = EnumColor.black.key;
			broNode.right.color = EnumColor.black.key;
			this.leftRotate(parent);
			removeTrue(node);
			//Node top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
			//}
			return;
		}
		// 当当前节点是右节点,并且兄弟节点的左节点是红色时
		if (node == parent.right && broNode.left.isRed()) {
			//System.out.println("当当前节点是右节点,并且兄弟节点的左节点是红色时");
			node.color = EnumColor.red.key;
			broNode.color =  node.parent.color;
			node.parent.color = EnumColor.black.key;
			broNode.left.color = EnumColor.black.key;
			this.rightRotate(parent);
			removeTrue(node);
			//Node top = this.getTopNode(node);
			//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
			//}
			return;
		}
		System.out.println("怎么到这了?"+(node == parent.right)+broNode.left.isBlack()+broNode.right.isBlack());
	}

	public void setColorBlack(Node node) {
		if(node.isRed()) {
			//System.out.println("红变黑");
			node.color = EnumColor.black.key;
		}else {
			setColorBlackTrue(node);
		}
		
	}

	public void setColorBlackTrue(Node node) {
		//System.out.println("开始变黑");
		if(node.parent==null) {
			return;
		}
		if(node.parent.isRed()) {
			//Node top = this.getTopNode(node);
			//this.checkNode(top);
			//System.out.println("父节点是红的");
			//System.out.println(this.getMinBlackLength(node)+":"+this.getMaxBlackLength(node));
			//System.out.println(this.getMinBlackLength(node.Brother())+":"+this.getMaxBlackLength(node.Brother()));
			//如果父节点是红的,则子节点必为黑色,旋转
			if(node.isLeftNode()) {
				if(node.Brother().left.isBlack()) {
					this.leftRotate(node.parent);
				}else {
					if(node.Brother().right.isRed()) {
						this.leftRotate(node.parent);
						node.parent.color = EnumColor.black.key;
						node.parent.Brother().color = EnumColor.black.key;
						node.parent.parent.color = EnumColor.red.key;
					}else {
						Node broNode = node.Brother();
						broNode.color = EnumColor.red.key;
						broNode.left.color = EnumColor.black.key;
						this.rightRotate(broNode);
						setColorBlackTrue(node);
					}
				}
			}else {
				if(node.Brother().right.isBlack()) {
					this.rightRotate(node.parent);
				}else {
					if(node.Brother().left.isRed()) {
						this.rightRotate(node.parent);
						node.parent.color = EnumColor.black.key;
						node.parent.Brother().color = EnumColor.black.key;
						node.parent.parent.color = EnumColor.red.key;
					}else {
						Node broNode = node.Brother();
						broNode.color = EnumColor.red.key;
						broNode.right.color = EnumColor.black.key;
						this.leftRotate(broNode);
						setColorBlackTrue(node);
					}
				}
			}
			//top = this.getTopNode(node);
			//this.checkNode(top);
		}else {
			//System.out.println("父节点是黑的");
			//如果父节点是黑色的,判断兄弟节点
			if(node.Brother().isRed()) {
				//如果兄弟节点是红色的
				//System.out.println("兄弟是红的");
				node.parent.color = EnumColor.red.key;
				node.Brother().color = EnumColor.black.key;
				if(node.isLeftNode()) {
					this.leftRotate(node.parent);
				}else {
					this.rightRotate(node.parent);
				}
				setColorBlackTrue(node);
			}
			else {
				Node broNode = node.Brother();
				//System.out.println("兄弟是黑的"+":自己"+node.color);
				//System.out.println(this.getMinBlackLength(node)+":"+this.getMaxBlackLength(node));
				//System.out.println(this.getMinBlackLength(broNode)+":"+this.getMaxBlackLength(broNode));
				if(node.isLeftNode()) {
					if(broNode.left.isBlack()) {
						//System.out.println("兄弟是黑的1");
						node.parent.color = EnumColor.red.key;
						this.leftRotate(node.parent);
						setColorBlackTrue(node.parent.parent);
						return;
					}
					if(broNode.left.isRed()&&broNode.right.isRed()) {
						//System.out.println("兄弟是黑的11");
						broNode.right.color = EnumColor.black.key;
						this.leftRotate(node.parent);
						return;
					}
					if(broNode.left.isRed()&&broNode.right.isBlack()) {
						//System.out.println("兄弟是黑的12");
						broNode.color = EnumColor.red.key;
						broNode.left.color = EnumColor.black.key;
						this.rightRotate(broNode);
						setColorBlackTrue(node);
						return;
					}
				}else {
					if(broNode.right.isBlack()) {
						//System.out.println("兄弟是黑的2");
						node.parent.color = EnumColor.red.key;
						this.rightRotate(node.parent);
						setColorBlackTrue(node.parent.parent);
						return;
					}
					if(broNode.right.isRed()&&broNode.left.isRed()) {
						//System.out.println("兄弟是黑的21");
						broNode.left.color = EnumColor.black.key;
						this.rightRotate(node.parent);
						return;
					}
					if(broNode.right.isRed()&&broNode.left.isBlack()) {
						//System.out.println("兄弟是黑的22");
						broNode.color = EnumColor.red.key;
						broNode.right.color = EnumColor.black.key;
						this.leftRotate(broNode);
						setColorBlackTrue(node);
						return;
					}
				}
			}
		}
		
	}

	public int getNodeSumNumber(Node node) {
		int num = 1;
		if(!node.left.isNullNode()) {
			num += getNodeSumNumber(node.left);
		}
		if(!node.right.isNullNode()) {
			num += getNodeSumNumber(node.right);
		}
		return num;
	}

	public int getNodeSum(Node node) {
		int num = node.value;
		if(!node.left.isNullNode()) {
			num += getNodeSum(node.left);
		}
		if(!node.right.isNullNode()) {
			num += getNodeSum(node.right);
		}
		return num;
	}

	public void printAllLeft(Node node) {
		System.out.print(node.value+",");
		if(!node.left.isNullNode()) {
			printAllLeft(node.left);
		}
		if(!node.right.isNullNode()) {
			printAllLeft(node.right);
		}
	}

	public void printAllRight(Node node) {
		System.out.print(node.value+",");
		if(!node.right.isNullNode()) {
			printAllRight(node.right);
		}
		if(!node.left.isNullNode()) {
			printAllRight(node.left);
		}
	}
}

枚举:

package test2019.mon01.红黑树;

import java.util.HashMap;
import java.util.Map;

/** 
 * Filename:  EnumColor.java 
 * Description: 
 * Company:     sendinfo.com.cn Inc.
 * @author: guzhangyan
 * @date: 2019年1月29日 上午11:40:05 
 */
public enum EnumColor {

	black(1,"黑节点"),
	red(0,"红节点");
	
	public int key;
	
	public String value;
	
	EnumColor(int key,String value){
		this.key = key;
		this.value = value;
	}
	
	public static Map<Integer,String> map = new HashMap<>();
	public static String getColorValue(int key) {
		if(map.isEmpty()) {
			EnumColor[] colors = EnumColor.values();
			for (EnumColor color : colors) {
				map.put(color.key, color.value);
			}
		}
		return map.get(key);
	}
}

新NodeAction代码
把部分功能合并

package test2019.mon01.红黑树;

/**
 * Filename: NodeAction.java Description:
 * 
 * @author: guzhangyan
 * @date: 2019年1月29日 上午9:57:39
 */
public class NodeAction {

	// 左旋
	public void rightRotate(Node node) {
		Node left = node.left;
		Node parnet = node.parent;
		Node leftRight = left.right;
		if (parnet != null) {
			if (parnet.left == node) {
				parnet.left = left;
			} else {
				parnet.right = left;
			}
			left.parent = parnet;// 对接父节点和左节点
		} else {
			left.parent = null;
		}
		if (leftRight != null) {
			leftRight.parent = node;
		}
		node.left = leftRight;// 对接左节点的右节点和本节点
		node.parent = left;
		left.right = node;// 换本节点和左节点的位置
	}

	// 右旋
	public void leftRotate(Node node) {
		Node right = node.right;
		Node parnet = node.parent;
		Node rightLeft = right.left;
		if (parnet != null) {
			if (parnet.left == node) {
				parnet.left = right;
			} else {
				parnet.right = right;
			}
			right.parent = parnet;// 对接父节点和右节点
		} else {
			right.parent = null;
		}
		if (rightLeft != null) {
			rightLeft.parent = node;
		}
		node.right = rightLeft;// 对接右节点的左节点和本节点
		node.parent = right;
		right.left = node;// 换本节点和右节点的位置
	}

	// 添加左节点
	public void addLeftNode(Node parent, Node node) {
		parent.left = node;
		node.parent = parent;
		node.left = Node.nullNode(node, EnumColor.black.key);
		node.right = Node.nullNode(node, EnumColor.black.key);
		node.color = EnumColor.red.key;
		addRotate(node);
	}

	// 添加右节点
	public void addRightNode(Node parent, Node node) {
		parent.right = node;
		node.parent = parent;
		node.left = Node.nullNode(node, EnumColor.black.key);
		node.right = Node.nullNode(node, EnumColor.black.key);
		node.color = EnumColor.red.key;
		addRotate(node);
	}

	// 添加之后旋转
	public void addRotate(Node node) {
		Node parent = node.parent;
		if (parent == null) {
			node.color = EnumColor.black.key;
			return;
		}
		if (parent.isBlack()) {
			return;// 父节点是黑色,不需要改动
		}
		// 当父节点是红色时,判断叔节点的颜色
		Node groudPNode = parent.parent;// 爷节点
		if (groudPNode == null) {
			parent.color = EnumColor.black.key;
			return;// 爷节点不存在时,结束
		}
		Node parBroNode = groudPNode.left;
		if (groudPNode.left == parent) {
			parBroNode = groudPNode.right;
		}
		if (parBroNode.isBlack()) {
			// 叔节点为黑时
			if (node == parent.left) {
				// 节点是左节点
				if (groudPNode.left == parent) {
					// 如果父节点是左节点
					// 爷右旋
					this.rightRotate(groudPNode);
					parent.color = EnumColor.black.key;
					groudPNode.color = EnumColor.red.key;
				} else {
					// 如果父节点是右节点
					// 父右旋
					this.rightRotate(parent);
					// 爷左旋
					this.leftRotate(groudPNode);
					groudPNode.color = EnumColor.red.key;
					node.color = EnumColor.black.key;
				}
			} else {
				// 节点是右节点
				if (groudPNode.left == parent) {
					// 如果父节点是左节点
					// 父左旋
					this.leftRotate(parent);
					// 爷右旋
					this.rightRotate(groudPNode);
					groudPNode.color = EnumColor.red.key;
					node.color = EnumColor.black.key;
				} else {
					// 如果父节点是右节点
					// 爷右旋
					this.leftRotate(groudPNode);
					parent.color = EnumColor.black.key;
					groudPNode.color = EnumColor.red.key;
				}
			}
		} else {
			// 叔节点为红节点时
			// 父节点和叔节点变黑,爷节点变红
			// 爷节点进行相同操作
			parent.color = EnumColor.black.key;
			parBroNode.color = EnumColor.black.key;
			groudPNode.color = EnumColor.red.key;
			addRotate(groudPNode);
		}
	}

	public void addNode(Node parent, Node node) {
		if (parent.value > node.value) {
			if (parent.left.isNullNode()) {
				this.addLeftNode(parent, node);
			} else {
				addNode(parent.left, node);
			}
		} else {
			if (parent.right.isNullNode()) {
				this.addRightNode(parent, node);
			} else {
				addNode(parent.right, node);
			}
		}
	}

	// 判断要删谁
	public void remove(Node node, int value) {
		if (node.value.equals(value)) {
			remove(node);
			return;
		}
		if (node.value - value > 0) {
			if (!node.left.isNullNode()) {
				remove(node.left, value);
			}
		} else {
			if (!node.right.isNullNode()) {
				remove(node.right, value);
			}
		}
	}

	public void remove(Node node) {
		if ((!node.left.isNullNode()) && (!node.right.isNullNode())) {
			Node besideNode = getBesideNode(node);
			node.value = besideNode.value;
			removeTrue(besideNode);
			return;
		}
		removeTrue(node);
	}

	// 获取要换的节点
	public Node getBesideNode(Node node) {
		return getBestRight(node.left);
	}

	public Node getBestRight(Node node) {
		if (node.right.isNullNode()) {
			return node;
		}
		return getBestRight(node.right);
	}

	// 删除
	public void removeTrue(Node node) {
		if (node.parent == null) {
			System.out.println("我是根节点");
			if (!node.left.isNullNode()) {
				node.copyOfOld(node.left);
				node.parent = null;
				node.color = EnumColor.black.key;
				return;
			}
			if (!node.right.isNullNode()) {
				node.copyOfOld(node.right);
				node.parent = null;
				node.color = EnumColor.black.key;
				return;
			}
			System.out.println("我是最后一个了,不知道怎么删除了");
			return;
		}
		if (node.isBlack()) {
			deleteBefore(node);
		}
		deleteNode(node);
	}

	// 删除前的校验
	public void deleteBefore(Node node) {

		Node parent = node.parent;
		if (node.parent == null) {
			return;
		}
		Node broNode = node.Brother();
		if (broNode.isRed()) {
			parent.color = EnumColor.red.key;
			broNode.color = EnumColor.black.key;
			if (parent.left == node) {
				this.leftRotate(parent);
			} else {
				this.rightRotate(parent);
			}
			deleteBefore(node);
			return;
		}
		if (broNode.left.isBlack() && broNode.right.isBlack()) {
			broNode.color = EnumColor.red.key;
			if (node.parent.isBlack()) {
				deleteBefore(node.parent);
			} else {
				node.parent.color = EnumColor.black.key;
			}
			return;
		}
		if (node == parent.left && broNode.right.isBlack()) {
			broNode.color = EnumColor.red.key;
			broNode.left.color = EnumColor.black.key;
			this.rightRotate(broNode);
			deleteBefore(node);
			return;
		}
		if (node == parent.right && broNode.left.isBlack()) {
			broNode.color = EnumColor.red.key;
			broNode.right.color = EnumColor.black.key;
			this.leftRotate(broNode);
			deleteBefore(node);
			return;
		}
		if (node == parent.left && broNode.right.isRed()) {
			broNode.color = node.parent.color;
			node.parent.color = EnumColor.black.key;
			broNode.right.color = EnumColor.black.key;
			this.leftRotate(parent);
			return;
		}
		if (node == parent.right && broNode.left.isRed()) {
			broNode.color = node.parent.color;
			node.parent.color = EnumColor.black.key;
			broNode.left.color = EnumColor.black.key;
			this.rightRotate(parent);
			return;
		}
		System.out.println("怎么到这了?" + (node == parent.right) + broNode.left.isBlack() + broNode.right.isBlack());
	}

	// 真删除接口
	public void deleteNode(Node node) {
		Node parent = node.parent;
		if (!node.left.isNullNode()) {
			node.left.parent = parent;
			if (node == parent.left) {
				parent.left = node.left;
			} else {
				parent.right = node.left;
			}
		} else if (!node.right.isNullNode()) {
			node.right.parent = parent;
			if (node == parent.left) {
				parent.left = node.right;
			} else {
				parent.right = node.right;
			}
		} else {
			if (node == parent.left) {
				parent.left = Node.nullNode(node, EnumColor.black.key);
			} else {
				parent.right = Node.nullNode(node, EnumColor.black.key);
			}
		}
	}

	/** 以下都是辅助接口 */
	public Node getTopNode(Node node) {
		Node top = node;
		while (top.parent != null) {
			top = top.parent;
		}
		return top;
	}

	public void checkNode(Node node) {
		if (!node.left.isNullNode()) {
			if (node.left.value > node.value) {
				System.out.println("出错了");
				return;
			}
			if (node.isRed()) {
				if (node.left.isRed()) {
					System.out.println("左双红:" + node.value + ":" + node.left.value);
					return;
				}
			}
			this.checkNode(node.left);
		}
		if (!node.right.isNullNode()) {
			if (node.right.value < node.value) {
				System.out.println("出错了");
				return;
			}
			if (node.isRed()) {
				if (node.right.isRed()) {
					System.out.println("右双红:" + node.value + ":" + node.right.value);
					return;
				}
			}
			this.checkNode(node.right);
		}
	}

	public int getNodeSumNumber(Node node) {
		int num = 1;
		if (!node.left.isNullNode()) {
			num += getNodeSumNumber(node.left);
		}
		if (!node.right.isNullNode()) {
			num += getNodeSumNumber(node.right);
		}
		return num;
	}

	public int getNodeSum(Node node) {
		int num = node.value;
		if (!node.left.isNullNode()) {
			num += getNodeSum(node.left);
		}
		if (!node.right.isNullNode()) {
			num += getNodeSum(node.right);
		}
		return num;
	}

	public int getMinLength(Node node) {
		if (node.isNullNode()) {
			return 0;
		}
		int leftlength = getMinLength(node.left);
		int rightlength = getMinLength(node.right);
		return (leftlength > rightlength ? rightlength : leftlength) + 1;
	}

	public int getMaxLength(Node node) {
		if (node.isNullNode()) {
			return 0;
		}
		int leftlength = getMaxLength(node.left);
		int rightlength = getMaxLength(node.right);
		return (leftlength < rightlength ? rightlength : leftlength) + 1;
	}

	public int getMinBlackLength(Node node) {
		if (node.isNullNode()) {
			return 0;
		}
		int leftlength = getMinBlackLength(node.left);
		int rightlength = getMinBlackLength(node.right);
		return (leftlength > rightlength ? rightlength : leftlength) + (node.isBlack() ? 1 : 0);
	}

	public int getMaxBlackLength(Node node) {
		if (node.isNullNode()) {
			return 0;
		}
		int leftlength = getMaxBlackLength(node.left);
		int rightlength = getMaxBlackLength(node.right);
		return (leftlength < rightlength ? rightlength : leftlength) + (node.isBlack() ? 1 : 0);
	}

	public void printAllLeft(Node node) {
		System.out.print(node.value + ",");
		if (!node.left.isNullNode()) {
			printAllLeft(node.left);
		}
		if (!node.right.isNullNode()) {
			printAllLeft(node.right);
		}
	}

	public void printAllRight(Node node) {
		System.out.print(node.value + ",");
		if (!node.right.isNullNode()) {
			printAllRight(node.right);
		}
		if (!node.left.isNullNode()) {
			printAllRight(node.left);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_33321609/article/details/86702550