因为算法课设需要,要实现红黑树的实验及具体演示步骤。
源码参考链接:https://blog.youkuaiyun.com/cdnight/article/details/10583177
一、红黑树特点
(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
根据这五条特性可以知道红黑树一直是平衡的,且该查找树时间复杂度为 O(log(n))
二、红黑树构造
1.构造红黑树单元
public class TreeUnit {
public String color = "red";
public boolean isRed = true;
public char indexNO = 'A';
public TreeUnit _parent = null;
public TreeUnit _leftChild = null;
public TreeUnit _rightChild = null;
public boolean isNIL = false;
}
2.查,插,删
查
private void recursion_search(TreeUnit _currentNode, char indexNO) {
if (_currentNode == null) {
return;
}
if (indexNO == _currentNode.indexNO) {
this.search_result = true;
return;
}
if (indexNO < _currentNode.indexNO) {
if (_currentNode._leftChild == null) {
return;
}
recursion_search(_currentNode._leftChild, indexNO);
return;
}
if (indexNO > _currentNode.indexNO) {
if (_currentNode._rightChild == null) {
return;
}
recursion_search(_currentNode._rightChild, indexNO);
}
}
增
public boolean insert(char indexNO) {
if (this._rootNode == null) {
this._rootNode = new TreeUnit();
this._rootNode.indexNO = indexNO;
this._rootNode.isRed = false;
return true;
}
TreeUnit parentUnit = recursion_search_fitParentNode(this._rootNode, indexNO);
if (parentUnit == null) {
return false;
}
TreeUnit minNode = new TreeUnit();
minNode.isRed = true;
minNode.indexNO = indexNO;
minNode._parent = parentUnit;
if (indexNO < parentUnit.indexNO) {
parentUnit._leftChild = minNode;
} else if (indexNO > parentUnit.indexNO) {
parentUnit._rightChild = minNode;
} else {
return false;
}
recursion_fixup_after_insert(minNode);
return true;
}
删
public boolean delete(char indexNO) {
TreeUnit originNode = search_node(indexNO);
TreeUnit rec_node = null;
TreeUnit nilNode = new TreeUnit();
nilNode.isNIL = true;
nilNode.isRed = false;
if (originNode == null) {
return false;
}
TreeUnit realDeletedNode = originNode;
if (originNode._rightChild == null) {
realDeletedNode = originNode;
} else {
realDeletedNode = recursion_search_real_deletedNode(originNode._rightChild);
}
if (realDeletedNode.indexNO == originNode.indexNO) {
TreeUnit parentNode = originNode._parent;
if (parentNode == null) {
if (originNode._leftChild == null) {
this._rootNode = null;
rec_node = null;
return true;
}
this._rootNode = originNode._leftChild;
this._rootNode._parent = null;
this._rootNode.isRed = false;
return true;
}
if (parentNode != null) {
boolean isLeft = false;
if (parentNode._leftChild != null && parentNode._leftChild.indexNO == originNode.indexNO) {
isLeft = true;
}
if (originNode.isRed) {
if (isLeft) {
parentNode._leftChild = null;
} else {
parentNode._rightChild = null;
}
return true;
}
boolean hasLeftChild = false;
if (originNode._leftChild != null) {
hasLeftChild = true;
}
if (isLeft) {
parentNode._leftChild = originNode._leftChild;
if (originNode._leftChild != null) {
originNode._leftChild._parent = parentNode;
}
} else if (!isLeft) {
parentNode._rightChild = originNode._leftChild;
if (originNode._leftChild != null) {
originNode._leftChild._parent = parentNode;
}
}
if (hasLeftChild) {
if (isLeft) {
recursion_fixup_afterDeletion(parentNode._leftChild);
} else {
recursion_fixup_afterDeletion(parentNode._rightChild);
}
return true;
}
nilNode._parent = parentNode;
if (isLeft) {
parentNode._leftChild = nilNode;
recursion_fixup_afterDeletion(parentNode._leftChild);
} else {
parentNode._rightChild = nilNode;
recursion_fixup_afterDeletion(parentNode._rightChild);
}
delNILNode(nilNode);
return true;
}
} else {
originNode.indexNO = realDeletedNode.indexNO;
TreeUnit parentNode = realDeletedNode._parent;
boolean isLeft = true;
if (parentNode._rightChild != null && parentNode._rightChild.indexNO == realDeletedNode.indexNO) {
isLeft = false;
}
if (realDeletedNode.isRed) {
if (isLeft) {
parentNode._leftChild = null;
return true;
}
parentNode._rightChild = null;
return true;
}
if (!realDeletedNode.isRed && realDeletedNode._rightChild != null && !realDeletedNode._rightChild.isNIL) {
if (isLeft) {
parentNode._leftChild = realDeletedNode._rightChild;
realDeletedNode._rightChild._parent = parentNode;
recursion_fixup_afterDeletion(realDeletedNode._leftChild);
return true;
}
System.out.println("【当真实节点为黑色并且拥有红色右子节点时,删除真实节点,将右子节点提升到同样位置,右子节点参与到位置调整】");
parentNode._rightChild = realDeletedNode._rightChild;
realDeletedNode._rightChild._parent = parentNode;
recursion_fixup_afterDeletion(parentNode._rightChild);
return true;
}
if (!realDeletedNode.isRed && (realDeletedNode._rightChild == null || (realDeletedNode._rightChild != null && realDeletedNode._rightChild.isNIL))) {
nilNode._parent = parentNode;
if (isLeft) {
parentNode._leftChild = nilNode;
} else {
parentNode._rightChild = nilNode;
}
recursion_fixup_afterDeletion(nilNode);
delNILNode(nilNode);
return true;
}
}
return true;
}
三、swing界面构造
1.显示单元
public class GraphNodeViewModel {
public char indexNO = 'A';
public boolean isRed = true;
public int xIndex = 0;
public int yIndex = 0;
public int locX = 0;
public int locY = 0;
public int HSep = 0;
public int VSep = 0;
public Object _cellObject = null;
public GraphNodeViewModel _parent = null;
public GraphNodeViewModel leftChild = null;
public GraphNodeViewModel rightChild = null;
public float leftNO = 0.0F;
public float rightNO = 0.0F;
public int leftChildLocX = 0;
public int rightChildLocX = 0;
}
2.增删查演示
增
删
还可以进行红黑树手动修改,本博客不做演示
源码在github中