public class BinarySearchTree> extends BinaryTree implements ITree{
protected enum Position {
LEFT, RIGHT
};
public BinarySearchTree(){
}
public Node getNode(E data){
Node node = root;
while(node != null){
if(data.compareTo(node.element) == 0){
return node;
}else if(data.compareTo(node.element) < 0){
node = node.left;
}else{
node = node.right;
}
}
return null;
}
protected Node getLeafLeftNode(Node node){
Node tNode = node;
if(tNode == null)
return tNode;
while(tNode.left != null){
tNode = tNode.left;
}
return tNode;
}
@SuppressWarnings("unchecked")
@Override
public boolean add(E data){
Node newNode = null;
if(this.creator == null)
newNode = new Node(data);
else
newNode = this.creator.createNewNode(data, null);
if(root == null){
root = newNode;
root.parent = null;
}else{
Node parent;
Node t = root;
int cmp;
do{
parent = t;
cmp = data.compareTo(parent.element);
if(cmp < 0){
t = t.left;
}else if(cmp > 0){
t = t.right;
}else{
// ì¼ë ë ê·¸ë¥ ë®ì´ìì°ëê² ì¼ë°ì ì¸ë¯..?
System.out.println("ë°ì´í° ì¤ë³µìë¨");
return false;
}
}while( t != null);
if(cmp < 0){
parent.left = newNode;
newNode.parent = parent;
}else{
parent.right = newNode;
newNode.parent = parent;
}
}
return true;
}
@SuppressWarnings("unchecked")
protected Node addAndGetNode(E data){
Node newNode = null;
if(this.creator == null)
newNode = new Node(data);
else
newNode = this.creator.createNewNode(data, null);
if(root == null){
root = newNode;
root.parent = null;
}
insertNode(root, newNode);
return newNode;
}
// recursive add
private Node insertNode(Node currentParent, Node newNode) {
if (currentParent == null)
return newNode;
else if (newNode.element.compareTo(currentParent.element) > 0){
currentParent.right = insertNode(currentParent.right, newNode);
currentParent.right.parent = currentParent;
}
else if (newNode.element.compareTo(currentParent.element) < 0 ){
currentParent.left = insertNode(currentParent.left, newNode);
currentParent.left.parent = currentParent;
}
return currentParent;
}
@Override
public E remove(E data){
Node removeNode = getNode(data);
Node replaceNode = getReplacementNode(removeNode);
replaceNodeWithNode(removeNode, replaceNode);
return data;
}
public Node removeAndGetNode(E data){
Node removeNode = getNode(data);
if(removeNode != null){
Node replaceNode = getReplacementNode(removeNode);
replaceNodeWithNode(removeNode, replaceNode);
}
return removeNode;
}
protected Node getReplacementNode(Node nodeToRemoved) {
Node replaceNode = null;
if(nodeToRemoved.left != null && nodeToRemoved.right == null){
replaceNode = nodeToRemoved.left;
}else if(nodeToRemoved.right != null && nodeToRemoved.left == null){
replaceNode = nodeToRemoved.right;
}else if(nodeToRemoved.left != null && nodeToRemoved.right != null){
// ì¤ë¥¸ìª½ ë
¸ëìì ê°ì¥ ì¼ìª½ì ìë ë
¸ë를 ì°¾ëë¤.
// ì¼ìª½ ë
¸ëìì ê°ì¥ ì¤ë¥¸ìª½ì ìë ë
¸ë를 ì°¾ìë ëë¤.
replaceNode = getLeafLeftNode(nodeToRemoved.right);
if(replaceNode == null){
// ìì í ë
¸ëì ì¤ë¥¸ìª½ ë
¸ëê° ì¼ìª½ ë
¸ëê° ìë¤ë©´
// ê·¸ë¥ ì¤ë¥¸ìª½ ë
¸ëë¡ ëì í¨
replaceNode = nodeToRemoved.right;
}
}
return replaceNode;
}
protected void replaceNodeWithNode(Node nodeToRemoved, Node replacementNode) {
// leaf ë
¸ë를 ìì íë¤ë©´ replacementNode ê° null ì¼ìë ìë¤.
if(replacementNode != null){
// ëì²´ í ë
¸ëì ì¤ë¥¸ìª½ ì¼ìª½ì ë°ê¾¸ê¸° ì ì 미리 ì ì¥í´ ëëë¤. ì²ìì ëì²´í ë
¸ëì ì¤ë¥¸ìª½ ì¼ìª½ë¶í° ë°ê¾¼ë¤.
// 1.ì¼ìª½ì ê°ì¥ ì¤ë¥¸ìª½ì ì ííìê²½ì° ë°ì²´í ë
¸ëì ì¼ìª½ ììì ìììë ìë¤.
Node replacementNodeLeft = replacementNode.left;
// 2.ì¤ë¥¸ìª½ì ê°ì§ì¼ìª½ì ì ííìê²½ì° ëì²´í ë
¸ëì ì¤ë¥¸ìª½ ììì ìììë ìë¤.
Node replacementNodeRight = replacementNode.right;
// ëì²´í ë
¸ë <-> ìì í ë
¸ëì ì쪽 ìì
// ** ìì í ë
¸ëì ëì²´í ë
¸ëê° ë°ë¡ ë¶ì´ ìë¤ë©´ ìì í ë
¸ëì ë¶ëª¨ë¥¼ ëì²´í ë
¸ëë¡ ë°ê¿ì£¼ê¸°ë§íë©´ë¨**
// ìì í ë
¸ëì ì쪽 ììì ëì²´í ë
¸ëì ë£ì´ì¤ë¤.
Node nodeToRemoveLeft = nodeToRemoved.left;
// ìì í ë
¸ëì ì¼ìª½ì´ ìë¤ë©´, **ê·¼ë° ìì í ë
¸ëì ì¼ìª½ì´ ëì²´í ë
¸ëê° ìëë¼ë©´**
if(nodeToRemoveLeft != null && !nodeToRemoveLeft.equals(replacementNode)){
replacementNode.left = nodeToRemoveLeft;
nodeToRemoveLeft.parent = replacementNode;
}
Node nodeToRemoveRight = nodeToRemoved.right;
// ìì í ë
¸ëì ì¤ë¥¸ìª½ì´ ìë¤ë©´, **ê·¼ë° ìì í ë
¸ëì ì¤ë¥¸ìª½ì´ ëì²´í ë
¸ëê° ìëë¼ë©´**
if(nodeToRemoveRight != null && !nodeToRemoveRight.equals(replacementNode)){
replacementNode.right = nodeToRemoveRight;
nodeToRemoveRight.parent = replacementNode;
}
// ëì²´í ë
¸ëì ë¶ëª¨ <-> ëì²´í ë
¸ëì ìì (ëì²´í ë
¸ëê° ë¹ ì§ë¯ë¡)
// ìì í ë
¸ëì ì¤ë¥¸ìª½ ë
¸ëì 맨ì¼ìª½ ë
¸ë(ëì²´í ë
¸ë) ì ì¤ë¥¸ìª½ ììì ìììë ìë¤.
Node replacementParent = replacementNode.parent;
// ëì²´í ë
¸ëì ë¶ëª¨ê° ìê³ , **ëì²´í ë
¸ëì ë¶ëª¨ê° ìì í ê²ì ìëë¼ë©´**
if(replacementParent != null && !replacementParent.equals(nodeToRemoved)){
// ëì²´í ë
¸ëê° ë¶ëª¨ì ì¼ìª½ì´ë¼ë©´(1.ì¤ë¥¸ìª½ìì ê°ì¥ ì¼ìª½ì ì ííìê²½ì°)
if(replacementParent.left != null && replacementParent.left.equals(replacementNode)){
// ëì²´í ë
¸ëì ì¤ë¥¸ìª½ì ëì²´í ë
¸ëì ë¶ëª¨ì ì¼ìª½ì¼ë¡ ì°ê²°í´ì¤ë¤.
replacementParent.left = replacementNodeRight;
if(replacementNodeRight != null){
// ë§ì½ ëì²´ë
¸ëì ì¤ë¥¸ìª½ì´ ììì´ ìë¤ë©´ ëì²´í ë
¸ëì ì¤ë¥¸ìª½ì ë¶ëª¨ë¥¼ ëì²´í ë
¸ëì ë¶ëª¨ë¡
replacementNodeRight.parent = replacementParent;
}
}else if(replacementParent.right != null && replacementParent.right.equals(replacementNode)){
// 1.ìì í ë
¸ëì ì¤ë¥¸ìª½ì ê°ì§ ì¼ìª½ ì ííì¼ë¯ë¡ ëì²´í ë
¸ëì ë¶ëª¨ì ì¤ë¥¸ìª½ì ììì¼ì´ ìë¤.
replacementParent.right = replacementNodeLeft;
if(replacementNodeLeft != null){
replacementNodeLeft.parent = replacementParent;
}
}
}
}
// ìì í ë
¸ëì ë¶ëª¨ <-> ëì²´ ë
¸ë
Node parent = nodeToRemoved.parent;
if(parent == null){
// ìì í ë
¸ëê° ë£¨í¸ ë
¸ë
root = replacementNode;
if(root != null)
root.parent = null;
}else if(parent.left != null && parent.left.equals(nodeToRemoved)){
// ìì í ë
¸ëê° ë¶ëª¨ì ì¼ìª½ ì´ë¼ë©´
parent.left = replacementNode;
if(replacementNode != null)
replacementNode.parent = parent;
}else if(parent.right != null && parent.right.equals(nodeToRemoved)){
// ìì í ë
¸ëê° ë¶ëª¨ì ì¤ë¥¸ìª½ ì´ë¼ë©´
parent.right = replacementNode;
if(replacementNode != null)
replacementNode.parent = parent;
}
}
public E remove2(E data){
Node removeNode = getNode(data);
if(removeNode.left == null && removeNode.right == null){
// leaf node
Node parent = removeNode.parent;
if(parent.left == removeNode){
parent.left = null;
}else if(parent.right == removeNode){
parent.right = null;
}
removeNode = null;
}
else if(removeNode.left != null && removeNode.right == null){
// ììì´ íê°ë°ììë¤.
Node parent = removeNode.parent;
Node child = removeNode.left;
if(parent.left == removeNode){
parent.left = child;
}else if(parent.right == removeNode){
parent.right = child;
}
removeNode = null;
}
else if(removeNode.right != null && removeNode.left == null){
// ììì´ íê°ë°ììë¤.
Node parent = removeNode.parent;
Node child = removeNode.right;
if(parent.left == removeNode){
parent.left = child;
}else if(parent.right == removeNode){
parent.right = child;
}
removeNode = null;
}
else if(removeNode.right != null && removeNode.left != null){
Node parent = removeNode.parent;
Node replaceNode = getLeafLeftNode(removeNode.right);
//System.out.println(replaceNode.element);
if(parent.left == removeNode){
parent.left = replaceNode;
replaceNode.left = removeNode.left;
if(replaceNode.right == null){
if(replaceNode != removeNode.right)
replaceNode.right = removeNode.right;
}
replaceNode.parent.left = null;
}else if(parent.right == removeNode){
parent.right = replaceNode;
replaceNode.left = removeNode.left;
// ëì í ë
¸ëì ì¼ìª½ì íì ìì§ë§ ì¤ë¥¸ìª½ì ìììë ìë¤.
if(replaceNode.right == null){
// ìì í ë
¸ëì ì¤ë¥¸ìª½ ë
¸ëê° ëì í ë
¸ëë ê°ì¼ë©´ ìë¡ ì°¸ì¡°íê²ë¨
if(replaceNode != removeNode.right)
replaceNode.right = removeNode.right;
}
replaceNode.parent.left = null;
}
removeNode = null;
}
return data;
}
public void rotateLeft(Node node){
System.out.println("ROTATE LEFT AT " + node);
Node parent = node.parent;
Position parentPosition = null;
if(parent != null){
if(node.equals(parent.left)){
parentPosition = Position.LEFT;
}else{
parentPosition = Position.RIGHT;
}
}
Node greater = node.right;
Node lesser = greater.left;
node.right = null;
greater.left = node;
node.parent = greater;
node.right = lesser;
if(lesser != null)
lesser.parent = node;
if(parentPosition != null){
if(parentPosition == Position.LEFT){
parent.left = greater;
}else{
parent.right = greater;
}
greater.parent = parent;
}else{
root = greater;
greater.parent = null;
}
}
public void rotateRight(Node node){
System.out.println("ROTATE RIGHT AT " + node);
Node parent = node.parent;
Position parentPosition = null;
if(parent != null){
if(node.equals(parent.left)){
parentPosition = Position.LEFT;
}else{
parentPosition = Position.RIGHT;
}
}
Node lesser = node.left;
Node greater = lesser.right;
node.left = null;
lesser.right = node;
node.parent = lesser;
node.left = greater;
if(greater != null)
greater.parent = node;
if(parentPosition != null){
if(parentPosition == Position.LEFT){
parent.left = lesser;
}else{
parent.right = lesser;
}
lesser.parent = parent;
}else{
root = lesser;
lesser.parent = null;
}
}
}