์ด์ง ํ์ ํธ๋ฆฌ๋ฅผ ์ดํดํ๊ธฐ ์ํด์๋ ํธ๋ฆฌ์ ๋ํ ๊ธฐ๋ณธ ๊ฐ๋ ๋ฐ ์ฉ์ด ์ ์ด์ง ํธ๋ฆฌ์ ์ข ๋ฅ์ ๊ธฐ๋ณธ์ ๋ํ ์ง์์ด ์์ด์ผ ์ํํ ์ดํด๊ฐ ๊ฐ๋ฅํ๋ ์์ง ์ดํด๊ฐ ๋ถ์กฑํ ์ฌ๋๋ค์ ๊ผญ ํ ๋ฒ ๊ฐ๋ณ๊ฒ ์ฝ๊ณ ์ค๋ ๊ฒ์ ์ถ์ฒํ๋ค.
์ด์ง ํ์ ํธ๋ฆฌ Binary Search Tree
์ด์ง ํ์ ํธ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์ด์ง ํธ๋ฆฌ๋ฅผ Binary Search Tree๋ผ๊ณ ํ๋ค.
๊ธฐ๋ณธ ์ ์ : ํธ๋ฆฌ์ ํค์๋ ๊ฐ์ด ๋ฐ๋์ ์กด์ฌํ๋ฉฐ ๊ฐ๋ค์ ๋น๊ตํ ์ ์๋ ์ง๋จ์ด ์กด์ฌํ๋ ์ ์์ ์ฌ์ผ ํ๋ค.
- ์กฐ๊ฑด 1 : ์ด๋ค ๋ ธ๋ N์ ๊ธฐ์ค์ผ๋ก ์ผ์ชฝ ์๋ธ ํธ๋ฆฌ ๋ ธ๋์ ๋ชจ๋ ํค ๊ฐ์ ๋ ธ๋ N์ ํค ๊ฐ ๋ณด๋ค ์์์ผ ํ๋ค.
- ์กฐ๊ฑด 2 : ์ค๋ฅธ์ชฝ ์๋ธ ํธ๋ฆฌ ๋ ธ๋์ ํค ๊ฐ์ ๋ ธ๋ N์ ํค ๊ฐ๋ณด๋ค ์ปค์ผ ํ๋ค.
- ์กฐ๊ฑด 3 : ๊ฐ์ ํค์ ๊ฐ์ ๊ฐ๋ ๋ ธ๋๋ ์กด์ฌํ์ง ์๋๋ค.
์กฐ๊ฑด์ ๊ฐ๋จํ๊ฒ ์ ๋ฆฌํ์๋ฉด ํ ๋ ธ๋๊ฐ ์์ ๋ ํด๋น ๋ ธ๋๋ณด๋ค ์์ผ๋ฉด ์ผ์ชฝ, ํฌ๋ฉด ์ค๋ฅธ์ชฝ์ผ๋ก ๋ฐฐ์น๊ฐ ๋ ๊ฒ๋ค์ด ์ด์ง ํ์ ํธ๋ฆฌ(BST)๊ฐ ๋๋ค๋ ๊ฒ์ด๋ค.
์ด์ ๊ฐ๋จํ๊ฒ ์ ์ด์ง ํ์ ํธ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋์ง์ ๋ํด์ ์์๋ณด์๋ฉด
์ด๋ฐ ์ด์ง ํ์ ํธ๋ฆฌ๊ฐ ์กด์ฌํ๋ค๊ณ ํด๋ณด์.
์ด ํ์ ํธ๋ฆฌ๋ฅผ ์ค์ ์ฐ์ฐ์ผ๋ก ํ๋ฉด ํค ๊ฐ์ ์ค๋ฆ ์ฐจ์์ผ๋ก ๊ฐ๋จํ ๊ตฌ์กฐ๋ก ๋ ธ๋๋ฅผ ์ป์ ์ ์๊ฒ ๋๋ค.
์ด ๊ฒ์ ์ค์ ๋ก ๊ตฌํํด๋ณด๋ฉฐ ์ดํดํด๋ณด์.
์ด์ง ํ์ ํธ๋ฆฌ ๋ง๋ค๊ธฐ
์ด์ง ํ์ ํธ๋ฆฌ๋ฅผ ๋ง๋ค๊ธฐ ์ํด์๋ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ํ์ฉํด์ผ ํ๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ํ ์ ๋ณด๋ฅผ ์ป๊ณ ์ถ๋ค๋ฉด ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ก ๊ฐ์ ๊ฐ๋ณ๊ฒ ์ฝ๊ณ ์ค๋ ๊ฒ์ ์ถ์ฒํ๋ค.
๋ ธ๋ ํด๋์ค ๋ง๋ค๊ธฐ
BST์ ๊ฐ๋ณ ๋
ธ๋๋ฅผ ๋ํ๋ด๋ ๊ฒ์ด ๋ฐ๋ก Node
ํด๋์ค ์ด๋ค. ์ด๋ ๋ค์๊ณผ ๊ฐ์ด 3๊ฐ์ ํ๋๋ก ๊ตฌ์ฑ๋๋ค.
- data : ๋ ธ๋๊ฐ ๊ฐ๋ ์ค์ง์ ๋ฐ์ดํฐ
- left : ๋ ธ๋์ ์ผ์ชฝ ์์
- right : ๋ ธ๋์ ์ค๋ฅธ์ชฝ ์์
์ด์ ๋ ธ๋ ํด๋์ค๋ฅผ ๋ง๋ค์์ผ๋ฏ๋ก ๋ ธ๋์ ์์ฑ์์ getter/setter ๋ฉ์๋๋ฅผ ์ถ๊ฐํ ํด๋์ค๋ฅผ ๋ง๋ค์ด๋ณด์.
public class BinarySearchTree {
public class Node {
public Node root;
private int data;
private Node left;
private Node right;
/* ์์ฑ์ */
public Node(int data){
this.setData(data);
setLeft(null);
setRight(null);
}
/* ๊ฐ์ข
getter / setter */
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
/*ํ์ ์ฐ์ฐ*/
public boolean find(int key){
Node currentNode = root;
}
}
public Node root; // bst์ ๋ฃจํธ ๋
ธ๋
public BinarySearchTree(){ // bst ์์ฑ์
root = null;
}
}
์ด์ ๊ธฐ๋ณธ์ ์ธ ํธ๋ฆฌ ๋ ธ๋๋ฅผ ๋ง๋ค์์ผ๋ ์ด์ง ํ์ ํธ๋ฆฌ๊ฐ ๋๊ธฐ ์ํ ์ญ์ ์ ์ฝ์ ์ฐ์ฐ์ ๋ํด์ ๊ตฌํํ๊ธฐ ์ ์ ํ์์ ์ผ๋ก ๊ตฌํ์ ํด์ผ ํ๋ ๊ฒ์ด ์๋ค. ๋ฐ๋ก ํ์ ์ฐ์ฐ์ธ๋ฐ, ์ญ์ ๋ ์ฝ์ ์ ๋ชจ๋ ํ์์ ๊ณผ์ ์ ๊ฑฐ์น ํ์ ์ด๋ฃจ์ด์ง๋ฏ๋ก ๋จผ์ ํ์์ ์์ํด๋ณด์.
ํ์ ์ฐ์ฐ
ํ์์ฐ์ฐ์์ ์ค์ํ ์ ์, ๋ฐ๋ก BST์ ํน์ฑ(์ผ์ชฝ ์์ ๋ ธ๋์ ๊ฐ์ ํ์ฌ ๋ ธ๋๋ณด๋ค ํญ์ ์์์ผํ๋ค)๊ณผ (์ค๋ฅธ์ชพ ์์ ๋ ธ๋์ ๊ฐ์ ํ์ฌ ๋ ธ๋์ ๊ฐ ๋ณด๋ค ํญ์ ์ปค์ผ ํ๋ค.)๋ผ๋ ํน์ง์ ๋ง์กฑํ๋ค๊ณ ๊ฐ์ ํ๊ณ ์ฐ์ฐ์ ํ๋ค๋ ๊ฒ์ด๋ค.
/*ํ์ ์ฐ์ฐ*/
public boolean find(int key){
Node currentNode = root;
while(currentNode != null){
// ํ์ฌ ๋
ธ๋์ ์ฐพ๋ ๊ฐ์ด ๊ฐ์ผ๋ฉด
if(currentNode.getData() == key){
return true;
}else if(currentNode.getData() > key){ // ์ฐพ๋ ๊ฐ์ด ํ์ฌ ๋
ธ๋๋ณด๋ค ์์ผ๋ฉด
currentNode = currentNode.left;
}else {// ์ฐพ๋ ๊ฐ์ด ํ์ฌ ๋
ธ๋๋ณด๋ค ํฌ๋ฉด
currentNode = currentNode.right;
}
}
return false;
}
์ฝ์ ์ฐ์ฐ
์ฝ์ ์ฐ์ฐ์์ ๊ฐ์ฅ ๋จผ์ ํ๋ ์ผ์ root๋ ธ๋๊ฐ ์กด์ฌํ๋์ง ํ์ธํ๋ ๊ฒ์ด๋ค.
root๋
ธ๋๊ฐ ์กด์ฌํ์ง ์๋๋ค๋ ์๋ฆฌ๋ ํด๋น ํธ๋ฆฌ์ ๋
ธ๋๊ฐ ์๋ค๋ ๋ป์ด๋ฏ๋ก ์๋ก์ด newNode
๋ฅผ root๋
ธ๋๋ก ๋ง๋ค์ด์ฃผ๊ณ return์ ํ๋ค.
๊ทธ๋ ์ง ์๋ค๋ฉด ๋
ธ๋์ ๊ฐ์ ๋น๊ตํด์ ํด ๋์ ์์ ๋ ์๋ก ๋น๊ตํ ๋ค, ์๋ฆฌ์ ์๋ง๋ ๋
ธ๋์ ์ฝ์
ํ๋ฉด ๋๋ค.
/*์ฝ์
์ฐ์ฐ*/
public void insert(int data) {
Node newNode = new Node(data); // ์ผ์ชฝ, ์ค๋ฅธ์ชฝ ์์ ๋
ธ๋๊ฐ null ์ด๋ฉฐ data ์ ๊ฐ์ด ์ ์ฅ๋ ์ ๋
ธ๋ ์์ฑ
if(root == null){// ๋ฃจํธ ๋
ธ๋๊ฐ ์์๋, ์ฆ ํธ๋ฆฌ๊ฐ ๋น์ด์๋ ์ํ์ผ ๋,
root = newNode;
return;
}
Node currentNode = root;
Node parentNode = null;
while(true) {
parentNode = currentNode;
if(data < currentNode.getData()) { // ํด๋น ๋
ธ๋๋ณด๋ค ํด ๋.
currentNode = currentNode.getLeft();
if(currentNode == null) { // ๋ ์ด์ ์์ ๋
ธ๋๊ฐ ์์ ๋, ์ฆ ์ฝ์
ํ ์ ์๋ ๋
parentNode.setLeft(newNode);
return ;
}
}else { // ํด๋น ๋
ธ๋๋ณด๋ค ์์ ๋.
currentNode = currentNode.getRight();
if(currentNode == null){ // ๋ ์ด์ ์์ ๋
ธ๋๊ฐ ์์ ๋, ์ฆ ์ฝ์
ํ ์ ์๋ ๋
parentNode.setRight(newNode);
return ;
}
}
}
}
์ญ์ ์ฐ์ฐ
์ญ์ ์ฐ์ฐ์ ์กฐ๊ธ ๊น๋ค๋ก์ด ๋ถ๋ถ์ด ์๋ค.
์ฐ๋ฆฌ๊ฐ ๋ง์ฝ ์์์ด ๋ชจ๋ ์๋ ํธ๋ฆฌ์ ๋
ธ๋๋ฅผ ์ญ์ ํ๋ค๊ณ ํ๋ค๋ฉด, ์ญ์ ํ ๋
ธ๋์ ์์๋ค์ ์ด๋ค ์์์ ์ํด ๋ฐฐ์น๋ ๊น?
์ด๊ฒ์ด ๋ชจํธํ๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๋ ์ญ์ ์ฐ์ฐ์์ ์ผ์ด์ค๋ฅผ ๋๋ ์ ์ฐ์ฐ์ ํ๋ค. ์ผ์ด์คํผ ํฌ๊ฒ 3๊ฐ์ง๊ฐ ์๋ค.
- ์์ ๋ ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ
- ํ๋์ ์์ ๋ ธ๋๋ฅผ ๊ฐ๋ ๊ฒฝ์ฐ
- ๋๊ฐ์ ์์ ๋ ธ๋๋ฅผ ๊ฐ๋ ๊ฒฝ์ฐ
์ญ์ ์ฐ์ฐ ๊ธฐ๋ณธ ์ธํ
/*์ญ์ ์ฐ์ฐ*/
public boolean delete(int data){
Node parentNode = root;
Node currentNode = root;
boolean isLeftChild = false;
while(currentNode.getData() != data) {
parentNode = currentNode;
if(currentNode.getData() > data) {
isLeftChild = true;
currentNode = currentNode.getLeft();
}else {
isLeftChild = false;
currentNode = currentNode.getRight();
}
if(currentNode == null){
return false;
}
}
if(currentNode.getLeft() == null && currentNode.getRight() == null) { // 1. ์์ ๋
ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ
if(currentNode == root) {
root = null; // ํด๋น ๋
ธ๋๊ฐ root node์ผ ๊ฒฝ์ฐ
}
if(isLeftChild) {
parentNode.setLeft(null); // ์ญ์ ํ ๋
ธ๋๊ฐ ๋ถ๋ชจ ๋
ธ๋์ ์ผ์ชฝ ์์์ผ ๊ฒฝ์ฐ
}
else {
parentNode.setRight(null); // ์ญ์ ํ ๋
ธ๋๊ฐ ๋ถ๋ชจ ๋
ธ๋์ ์ค๋ฅธ์ชฝ ์์์ผ ๊ฒฝ์ฐ
}
} else if(currentNode.getRight() == null){ // 2-1. ์์ ๋
ธ๋๊ฐ ํ๋์ธ ๊ฒฝ์ฐ(์ค๋ฅธ์ชฝ ์์์ด ์์ ๋)
parentNode.setLeft(currentNode.getLeft());
} else if(currentNode.getLeft() == null) { // 2-2. ์์ ๋
ธ๋๊ฐ ํ๋์ธ ๊ฒฝ์ฐ(์ผ์ชฝ ์์์ด ์์ ๋)
parentNode.setRight(currentNode.getRight());
} else { // 3. ์์์ด ๋์ธ ๊ฒฝ์ฐ
Node minimum = getMinumun(currentNode);
if(currentNode == root) {
root = minimum;
}else if (isLeftChild){
parentNode.setLeft(minimum);
}else {
parentNode.setLeft(currentNode.getLeft());
}
minimum.setLeft(currentNode.getLeft());
}
return false;
}
Node getMinumun(Node deleteNode) {
Node minimum = null;
Node minimumParent = null;
Node currentNode = deleteNode.getRight();
while(currentNode != null) {
minimumParent = minimum;
minimum = minimumParent;
currentNode = currentNode.getLeft();
}
if(minimum != deleteNode.getRight()){
minimumParent.setLeft(minimum.getRight());
minimum.setRight(deleteNode.getRight());
}
return minimum;
}
์ ์ฒด ์์ค ์ฝ๋
package theory.tree;
import java.util.Scanner;
public class BinarySearchTree {
public class Node {
private int data;
private Node left;
private Node right;
/* ์์ฑ์ */
public Node(int data){
this.setData(data);
setLeft(null);
setRight(null);
}
/* ๊ฐ์ข
getter / setter */
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
}
public Node root;
BinarySearchTree(){
root = null;
}
/*ํ์ ์ฐ์ฐ*/
public boolean find(int key){
Node currentNode = root;
while(currentNode != null){
// ํ์ฌ ๋
ธ๋์ ์ฐพ๋ ๊ฐ์ด ๊ฐ์ผ๋ฉด
if(currentNode.getData() == key){
return true;
}else if(currentNode.getData() > key){ // ์ฐพ๋ ๊ฐ์ด ํ์ฌ ๋
ธ๋๋ณด๋ค ์์ผ๋ฉด
currentNode = currentNode.getLeft();
}else {// ์ฐพ๋ ๊ฐ์ด ํ์ฌ ๋
ธ๋๋ณด๋ค ํฌ๋ฉด
currentNode = currentNode.getRight();
}
}
return false;
}
/*์ฝ์
์ฐ์ฐ*/
public void insert(int data) {
Node newNode = new Node(data); // ์ผ์ชฝ, ์ค๋ฅธ์ชฝ ์์ ๋
ธ๋๊ฐ null ์ด๋ฉฐ data ์ ๊ฐ์ด ์ ์ฅ๋ ์ ๋
ธ๋ ์์ฑ
if(root == null){// ๋ฃจํธ ๋
ธ๋๊ฐ ์์๋, ์ฆ ํธ๋ฆฌ๊ฐ ๋น์ด์๋ ์ํ์ผ ๋,
root = newNode;
return;
}
Node currentNode = root;
Node parentNode = null;
while(true) {
parentNode = currentNode;
if(data < currentNode.getData()) { // ํด๋น ๋
ธ๋๋ณด๋ค ํด ๋.
currentNode = currentNode.getLeft();
if(currentNode == null) {
parentNode.setLeft(newNode);
return ;
}
}else { // ํด๋น ๋
ธ๋๋ณด๋ค ์์ ๋.
currentNode = currentNode.getRight();
if(currentNode == null){
parentNode.setRight(newNode);
return ;
}
}
}
}
/*์ญ์ ์ฐ์ฐ*/
public boolean delete(int data){
Node parentNode = root;
Node currentNode = root;
boolean isLeftChild = false;
while(currentNode.getData() != data) {
parentNode = currentNode;
if(currentNode.getData() > data) {
isLeftChild = true;
currentNode = currentNode.getLeft();
}else {
isLeftChild = false;
currentNode = currentNode.getRight();
}
if(currentNode == null){
return false;
}
}
if(currentNode.getLeft() == null && currentNode.getRight() == null) { // 1. ์์ ๋
ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ
if(currentNode == root) {
root = null; // ํด๋น ๋
ธ๋๊ฐ root node์ผ ๊ฒฝ์ฐ
}
if(isLeftChild) {
parentNode.setLeft(null); // ์ญ์ ํ ๋
ธ๋๊ฐ ๋ถ๋ชจ ๋
ธ๋์ ์ผ์ชฝ ์์์ผ ๊ฒฝ์ฐ
}
else {
parentNode.setRight(null); // ์ญ์ ํ ๋
ธ๋๊ฐ ๋ถ๋ชจ ๋
ธ๋์ ์ค๋ฅธ์ชฝ ์์์ผ ๊ฒฝ์ฐ
}
} else if(currentNode.getRight() == null){ // 2-1. ์์ ๋
ธ๋๊ฐ ํ๋์ธ ๊ฒฝ์ฐ(์ค๋ฅธ์ชฝ ์์์ด ์์ ๋)
parentNode.setLeft(currentNode.getLeft());
} else if(currentNode.getLeft() == null) { // 2-2. ์์ ๋
ธ๋๊ฐ ํ๋์ธ ๊ฒฝ์ฐ(์ผ์ชฝ ์์์ด ์์ ๋)
parentNode.setRight(currentNode.getRight());
} else { // 3. ์์์ด ๋์ธ ๊ฒฝ์ฐ
Node minimum = getMinumun(currentNode);
if(currentNode == root) {
root = minimum;
}else if (isLeftChild){
parentNode.setLeft(minimum);
}else {
parentNode.setLeft(currentNode.getLeft());
}
minimum.setLeft(currentNode.getLeft());
}
return false;
}
Node getMinumun(Node deleteNode) {
Node minimum = null;
Node minimumParent = null;
Node currentNode = deleteNode.getRight();
while(currentNode != null) {
minimumParent = minimum;
minimum = minimumParent;
currentNode = currentNode.getLeft();
}
if(minimum != deleteNode.getRight()){
minimumParent.setLeft(minimum.getRight());
minimum.setRight(deleteNode.getRight());
}
return minimum;
}
}
๋๊ธ