각 노드의 loop는 존재하지 않는다.
그래프는 객체 간의 관계를 표현하지만 계층은 표현할 수 없다
트리는 계층을 표현할 수 있으므로 객체 간 관계와 계층을 표시한 그래프는 트리다.
위 트리의 경우 2 7 5 2 6 5 11 9 4
9개의 노드, 8개의 에지를 가짐
leftNode <= RootNode < RightNode
Full Binary Tree
모두 존재하거나 모두 존재하지 않는 트리
Complete Binary Tree
마지막 레벨을 제외한 모든 레벨이 완전하고 왼쪽부터 채워진 트리
Perfect Binary Tree
레벨과 노드 갯수가 모두 동일한 트리로 Full + Complete임
public void addChild(int input) { // 노드 삽입
// 노드 값이 중복되면 삽입없이 종료
if (searchingNode(input) != null) {
System.out.println("already exist in tree " + input);
return;
}
Node newNode = new Node(input);
if (root == null) { // 트리가 없다면 root 생성
root = newNode;
} else {
Node moveNode = root; // 움직일 노드
Node pointer;
while (true) {
pointer = moveNode;
if (input < pointer.data) {
moveNode = pointer.left;
if (moveNode == null) {
pointer.left = newNode;
return;
}
} else {
moveNode = pointer.right;
if (moveNode == null) {
pointer.right = newNode;
return;
}
}
}
}
}
개인적으로 트리의 삭제가 약간 헷갈렸다.
트리의 삭제는 세가지가 존재하는데 자식 노드가 두개 다 존재할 경우 트리의 구조를 유지시켜야 하기때문에 몇가지 조작이 필요했다.
public void deleteNode(int input) {
Node moveNode = root;
Node pointer = root;
boolean leftflag = true;
// 삭제 될 노드로 이동
while (moveNode.data != input) {
pointer = moveNode;
if (input < moveNode.data) {
leftflag = true;
moveNode = pointer.left;
} else {
leftflag = false;
moveNode = pointer.right;
}
}
Node replacementNode; // 변경될 노드
// 자식 노드가 없는 노드 삭제
if (moveNode.left == null && moveNode.right == null) {
if (moveNode == root) {
root = null;
}
if (leftflag) {
pointer.left = null;
} else {
pointer.right = null;
}
}
// 자식 노드가 한개 있는 노드 삭제
// 어차피 왼쪽만 있은 왼쪽만 지우면 끝
else if (moveNode.right == null) {
if (moveNode == root) {
root = null;
}
pointer.left = null;
}
// 오른쪽만 있다면 오른쪽만 삭제
else if (moveNode.left == null) {
if (moveNode == root) {
root = null;
}
pointer.right = null;
}
// 자식 노드가 두개일 때
else {
// 삭제될 노드의 오른쪽 트리 저장
Node subTree = moveNode.right;
// 삭제될 노드의 서브트리에서 가장 작은 노드 확인
replacementNode = subTree.left;
subTree.left = null;
// root 라면 그냥 바꿔줌
if (moveNode == root) {
root = replacementNode;
}
// flag 통해서 root 좌우측 판단
if (leftflag) {
pointer.left = replacementNode;
} else {
pointer.right = replacementNode;
}
// 바꿀 노드가 null이 아니라면
// 바꿀 노드의 오른쪽에 서브트리 결합
// 바꿀 노드가 서브트리면 null
// 바꿀 노드의 왼쪽에 기존 노드의 좌측 노드 결합
if (replacementNode != null) {
replacementNode.right = subTree;
if (replacementNode == subTree) {
replacementNode.right = null;
}
replacementNode.left = moveNode.left;
}
}
}
public void inOrder(Node node) { // left - root - right if (node != null) { inOrder(node.getLeft()); System.out.println(node.data); inOrder(node.getRight()); } }
public void preOrder(Node node) { // root - left - right if (node != null) { System.out.println(node.data); preOrder(node.getLeft()); preOrder(node.getRight()); } }
public void postOrder(Node node) { // left - right - root if (node != null) { postOrder(node.getLeft()); postOrder(node.getRight()); System.out.println(node.data); } }
public void addChild(int input) {
Node newNode = new Node(input);
if (root == null) { // 트리가 없다면 root 생성
root = newNode;
count++;
} else {
Node pointer = root; // 포인터
Node parent; // 포인터의 부모
while (true) {
parent = pointer;
if (input < parent.data) {
pointer = parent.left;
if (pointer == null) {
parent.left = newNode;
count++;
return;
}
} else {
pointer = parent.right;
if (pointer == null) {
parent.right = newNode;
count++;
return;
}
}
}
}
}
Node pointer = root; // 포인터
Node parent; // 포인터의 부모
while (true) {
parent = pointer;
if (count % 2 == 1) {
pointer = parent.left;
if (pointer == null) {
parent.left = newNode;
count++;
return;
}
} else {
pointer = parent.right;
if (pointer == null) {
parent.right = newNode;
count++;
return;
}
}