File Structure assignment, it works perfectly well
BTree.java
import java.io.*; import java.util.*; // 실제로 BTree를 구현할 class public class BTree { public BTreeNode rootNode; public BTree() { rootNode = new BTreeNode(); } public boolean insert(BTreeData data) throws Exception // 생성부분 완료 { StackBTreeData.javastack = new Stack (); // 삽입시 참조되는 순서를 저장하게 될 stack BTreeNode parentNode = null; BTreeNode currentNode = rootNode; BTreeNode newNode = null; currentNode = rootNode; int i=0; //int totalCount = while(currentNode != null) { parentNode = currentNode; stack.push(parentNode); // Stack에 부모노드들이 차근 차근 쌓아둔다.(나중에 split or merge시 사용) for(i=0;i data.key) // 만약 bucket의 키 값이, data key보다 클 경우 { // 그 의미는 곧 삽입해야할 곳을 찾았다는 의미 break; } } currentNode = currentNode.childNode[i]; // 실제 insert 될 곳의 node는 여기 들어간다. } if(parentNode == null) // root에 아무것도 없는 경우 { rootNode.data[0] = data; rootNode.elementCount = 1; } else // root노드가 비어있지 않은 경우(일반정인 경우라면)(그리고 여기선 순서대로 저장되야 한다. sort함수를 사용하자) { insertDataBTree(parentNode,data, null); splitNode(stack); } return true; } //실제 Data를 입력하는 함수이다. public void insertDataBTree(BTreeNode currentNode, BTreeData data, BTreeNode RChildNode) throws Exception { @SuppressWarnings("null") int elementIndex = currentNode.elementCount; int i=0; // 실제로 삽입될 index for( i = elementIndex-1 ; i>=0;i--) // 자료를 이동하는 함수 { int tempKey = currentNode.data[i].key; if(tempKey> data.key) // 한칸씩 땡기게 된다. { currentNode.data[i+1] = currentNode.data[i]; currentNode.childNode[i+2] = currentNode.childNode[i+1]; } else break; } currentNode.data[i+1] = data; // 실제 데이터 삽입부분, i--이므로 currentNode.childNode[i+2] = RChildNode; // 우 노드를 삽입한다(이는 merge와 split시 필요하다) currentNode.elementCount++; // } public void showBTree() // 출력 함수 { if(rootNode == null) { System.out.println("There is no data!!! BTree is empty!"); } else { showBTreeByRecur(rootNode); } } public void showBTreeByRecur(BTreeNode Node) // 출력 부분 { // post-order traversals. if(Node != null) { for(int i=0;i stack) // 분할 함수 부분 { BTreeNode parentTreeNode = null; BTreeNode currentTreeNode = null; BTreeNode newNode = null; BTreeData middleElement = null; BTreeNode tempNode; int middleIndex = 5/2; currentTreeNode = stack.pop(); // 가장 최상위 stack의 값을 가져온다. while(currentTreeNode != null) { //currentTreeNode = tempNode; if(currentTreeNode.elementCount >= 5) // 만약 5보다 element가 크다면(실제로 데이터는 M-1개 즉 4개밖에 저장하지 못한다) { newNode = new BTreeNode(); middleElement = new BTreeData(); middleElement = currentTreeNode.data[middleIndex]; // 중간요소를 저장한다. currentTreeNode.data[middleIndex] = null; // 이 부분을 없애준다. int j =0; int i; for(i= middleIndex + 1 ; i<5; i++) // 중간 이후의 노드들은 분할되기 위해서 다 복사된다. { newNode.data[j] = currentTreeNode.data[i]; newNode.childNode[j] = currentTreeNode.childNode[i]; currentTreeNode.data[i] = null; currentTreeNode.childNode[i] = null; j++; } newNode.childNode[j] = currentTreeNode.childNode[i]; // m원 트리에서 node개수는 m-1개 subTree는 m개이기 떄문에 currentTreeNode.childNode[i] = null; // 이 작업을 반드시 해줘야한다. newNode.elementCount = 5/2; // 분할되면 2개만 저장하게 된다.(5개 이므로) currentTreeNode.elementCount = 5/2; // 현재 노드의 element 개수도 반이 된다고 명시해준다. // 여기서부터는 상위 부모 노드를 가져온다. try { parentTreeNode = stack.pop(); // 부모노드 가져오기 insertDataBTree(parentTreeNode, middleElement, newNode); } catch(Exception e) // 더 이상 pop하지 못하면 이 예외가 발생하게 된다. { rootNode = new BTreeNode(); // root노드를 하나 새로이 다시 만들고 rootNode.data[0] = middleElement; // 중간값을 새로 집어 넣고 rootNode.elementCount++; // 전체 개수를 증가 시킨 후 rootNode.childNode[0] = currentTreeNode; // 왼쪽 subtree는 현재껄로 rootNode.childNode[1] = newNode; // 다른쪽은 새로운 걸로 삽입한다. } } currentTreeNode = parentTreeNode; // 계속해서 올라가야 한다. parentTreeNode = null; } } public boolean removeNode(int key) throws Exception { int i = 0; // counter 변수 //int index = 0; boolean isFind = false; // 만약 검색해서 해당 노드를 찾지 못할경우 이 flag가 쓰인다. BTreeNode parentNode = null; BTreeNode currentNode = null; Stack stack = new Stack (); // stack을 하나 생성한다(노드 분할 및 balance를 위해서 쓰인다) currentNode = rootNode; while(currentNode != null && isFind == false) // 이부분은 insert함수와 똑같지만, 찾을 때까지 수행하는 것만 다르다. { parentNode = currentNode; stack.push(parentNode); // Stack에 부모노드들이 차근 차근 쌓아둔다.(나중에 split or merge시 사용) for(i=0;i key) // 만약 bucket의 키 값이, data key보다 클 경우 { // 그 의미는 곧 삽입해야할 곳을 찾았다는 의미 break; } } currentNode = currentNode.childNode[i]; // 실제 insert 될 곳의 node는 여기 들어간다. } if(isFind == true) // 만약 원하는 키를 찾았다면 { // 먼저 leaf node가 잇는지 검사한다. if(parentNode.childNode[0] == null) // 현재노드가 아무것도 가리키지 않을 경우 { deleteKeyBTree(parentNode, i); // deleteKeyBt 를 수행하는 부분 } else // leaf 노드가 잇다면 { parentNode = replaceLeafNodeBTree(parentNode, i, stack); // leaf 노드의 맨 끝 부분을 끌어 당기는 함수 // replaceLeafNodebt를 수행한다. } if(parentNode.elementCount < 5/2) // 만약 최소 개수보다 작다면 { balanceBTree(stack); // } return true; } else { System.out.println("The Key cannot be found! Try this again"); return false; } } public void balanceBTree(Stack stack) throws Exception { BTreeNode parentNode = null; BTreeNode currentNode = null; BTreeNode newNode = null; BTreeNode leftNode = null; BTreeNode rightNode = null; BTreeData pivotData = new BTreeData(); // stack 가장 윗부분에 있는 node int index = 0; // parentNode로부터 currentNode의 위치를 받을 변수 int i= 0; currentNode = stack.pop(); if(currentNode.elementCount >= 5/2) // 만약 balance 유지할 필요가 없다면(1/2보다 크다) return; try { parentNode = stack.pop(); // 2번째 stack을 받는다(부모 노드) } catch(Exception e) // 만약 부모노드에 아무것도 없다면 return한다. { return; } for(int j=0;i = ((5/2) + 1))) { borrowRightNodeBTree(parentNode,currentNode,index,parentNode.childNode[index+1]); } else if(index > 0 && (parentNode.childNode[index-1].elementCount >= ((5/2) + 1))) // 왼쪼깅 다 많다면 { // 여기는 왼쪽에서 빌린다. borrowLeftNodeBTree(parentNode,currentNode,index,parentNode.childNode[index+1]); } else // 그렇지 않으면 merge한다. { mergeNodeBTree(stack,parentNode,currentNode,index); } } public void mergeNodeBTree(Stack stack, BTreeNode parentNode, BTreeNode currentNode, int index) throws Exception { BTreeNode leftNode = null; BTreeNode rightNode = null; BTreeData parentData = new BTreeData(); BTreeNode parentParentNode = null; //조상 노드. int i=0; int pivotIndex = 0; // 예외 처리 생략 // 오른쪽으로 병합하는 경우 if(index< parentNode.elementCount) { leftNode = currentNode; // 현재노드가 left node가 되고 rightNode = parentNode.childNode[index+1]; // 오른쪽 node는 parent의 오른쪽이 되고 pivotIndex = index; // pivot은 현재 index가 되고 parentData = parentNode.data[pivotIndex]; // 그 데이터는 원래 index가 되고 } else // 왼쪽으로 합병하는 경우 { leftNode = parentNode.childNode[index-1]; rightNode = currentNode; pivotIndex = index - 1; parentData = parentNode.data[pivotIndex]; } insertDataBTree(leftNode, parentData, rightNode.childNode[0]); // 0번째 요소에 왼쪽 data를 넣는다. 왼쪽에 parent 자료 추가 for(i=0;i stack) { BTreeNode returnNode = null; BTreeData leafNodeData = new BTreeData(); BTreeNode childNode = null; BTreeNode parentNode = deleteNode; int elementCount = index; do // stack에 하나하나 다 쌓아둔다(나중에 balance를 유지할 때 필요하다) { childNode = parentNode.childNode[elementCount]; // parentNode의 삭제될 부분 뒤부터 stack.push(childNode); // 하나하나 씩 stack에 쌓아 논다. elementCount = childNode.elementCount; // elementCount는 새로운 childNode의 elementCount가 되고 parentNode = childNode; // 반복하여 수행한다. }while(childNode.childNode[elementCount] != null); leafNodeData = childNode.data[childNode.elementCount-1]; // 가장 오른쪽 끝에 있는걸 가져오고 deleteNode.data[index] = leafNodeData; // 삭제할 노드의 끝부분에다가 왼쪽끝의 요소를 대체한다. deleteKeyBTree(deleteNode, elementCount-1); // 그리고 그 삭제될 바로 앞에 있는 요소를 삭제한다(원래 우리가 삭제하길 원했던 부분이다) returnNode = childNode; return returnNode; } public void deleteKeyBTree(BTreeNode parentNode, int index) // 삭제 후 요소들을 한칸 씩 당기는 함수 { int i=0; if(parentNode != null) { for(i = index + 1; i < parentNode.elementCount; i++) // 앞으로 한칸 씩 떙긴다 { parentNode.data[i-1] = parentNode.data[i]; parentNode.childNode[i] = parentNode.childNode[i+1]; } parentNode.data[parentNode.elementCount - 1] = null; // 요소를 하나 삭제하고 parentNode.childNode[parentNode.elementCount] = null; // 역시 끝에 포인터도 null로 만든다. parentNode.elementCount--; // 전체 요소의 개수를 줄이고 } } }
import java.io.*;
public class BTreeData // 데이터 부분
{
public int key;
public Object value;
BTreeData(int _key, Object _value) // 2개의 부분으로 overloading 되어 있다.
{
key = _key;
value = _value;
}
BTreeData()
{
key=0;
value = null;
}
}
BTreeNode.java
import java.io.*;
public class BTreeNode
{
public BTreeNode childNode[];
public BTreeData data[];
public int elementCount; // 총 Element Count가 있다.
BTreeNode()
{
childNode = new BTreeNode[6]; // M-5 트리, 추가로 하나의 여유분을 둔다.. 우선 insert한후에 split하기 위해서
data = new BTreeData[5];
}
public void setData(int index, BTreeData TreeData)
{
data[index] = TreeData;
}
}
mainFunction.java
import java.io.Console;
import java.util.Scanner;
public class mainFunction {
public static void main(String args[]) throws Exception
{
BTree bt = new BTree(); // B-Tree 생성
Scanner scan = new Scanner(System.in); // Scanner 생성
System.out.println("Welcome to B-Tree's world!!!!!");
int input=0;
do
{
System.out.println("\n1. Input Data"); // Menu 출력
System.out.println("2. Remove Data with Key value");
System.out.println("3. Show B-Tree by post-order traversal method");
System.out.println("Please Enter the menu number(Exit is 0)\n");
String temp = scan.nextLine(); // 입력받기
try
{
input = Integer.valueOf((temp)); // switch 문을 위해서 변환을 해준다.
}
catch(Exception e) // 예외 처리
{
System.out.println("Please enter the correct number please");
continue;
}
switch(input)
{
case 1: // 1번은 insert function
String temp1 = new String();
String temp2 = new String();
System.out.println("Please Enter the Key number");
temp1 = scan.nextLine();
System.out.println("Please Enter the Any String Data you want");
temp2 = scan.nextLine();
BTreeData tmpData = new BTreeData(Integer.valueOf(temp1),temp2); // 입력받은 값을 가지고 data를 생성한다.
if(bt.insert(tmpData))
System.out.println("Successful!");
else
System.out.println("Failed");
break;
case 2: // 2번은 remove function
String tempRemoveKey = new String();
System.out.println("Please Enter the key you want to remove from B-Tree");
tempRemoveKey = scan.nextLine();
if(bt.removeNode(Integer.valueOf(tempRemoveKey))) // 삭제한다.
System.out.println("Successful!");
else
System.out.println("Failed");
break;
case 3: // 3번은 출력
System.out.println("\nThe B-Tree will be shown soon\n");
bt.showBTree(); // 출력한다.
break;
case 0: // 0은 프로그램 종료
System.out.println("The program will be terminated");
break;
default:
System.out.println("Please Enter correct number");
break;
}
}while(input!=0);
}
}
/*
BTreeData b1 = new BTreeData(69, "b1"); BTreeData b2 = new BTreeData(7, "b2");
BTreeData b3 = new BTreeData(150, "b3"); BTreeData b4 = new BTreeData(19, "b4");
BTreeData b5 = new BTreeData(70, "b5"); BTreeData b6 = new BTreeData(20, "b6");
BTreeData b7 = new BTreeData(128, "b7"); BTreeData b8 = new BTreeData(18, "b8");
BTreeData b9 = new BTreeData(42, "b9"); BTreeData b10 = new BTreeData(120, "b10");
BTreeData b11 = new BTreeData(140, "b11"); BTreeData b12 = new BTreeData(16, "b12");
BTreeData b13 = new BTreeData(100, "b13"); BTreeData b14 = new BTreeData(26, "b14");
BTreeData b15 = new BTreeData(145, "b15"); BTreeData b16 = new BTreeData(15, "b16");
BTreeData b17 = new BTreeData(110, "b17"); BTreeData b18 = new BTreeData(30, "b18");
BTreeData b19 = new BTreeData(40, "b19"); BTreeData b20 = new BTreeData(132, "b20");
BTreeData b21 = new BTreeData(138, "b21"); BTreeData b22 = new BTreeData(50, "b22");
BTreeData b23 = new BTreeData(43, "b23"); BTreeData b24 = new BTreeData(130, "b24");
BTreeData b25 = new BTreeData(136, "b25"); BTreeData b26 = new BTreeData(41, "b26");
BTreeData b27 = new BTreeData(59, "b27"); BTreeData b28 = new BTreeData(54, "b28");
BTreeData b29 = new BTreeData(122, "b29"); BTreeData b30 = new BTreeData(124, "b3o");
bt.insert(b1); bt.insert(b2); bt.insert(b3); bt.insert(b4);
bt.insert(b5); bt.insert(b6); bt.insert(b7); bt.insert(b8);
bt.insert(b9); bt.insert(b10); bt.insert(b11); bt.insert(b12);
bt.insert(b13); bt.insert(b14); bt.insert(b15); bt.insert(b16);
bt.insert(b17); bt.insert(b18); bt.insert(b19); bt.insert(b20);
bt.insert(b21); bt.insert(b22); bt.insert(b23); bt.insert(b24);
bt.insert(b25); bt.insert(b26); bt.insert(b27); bt.insert(b28);
bt.insert(b29); bt.insert(b30);
System.out.println("All datas have been inserted, it will be shown by post-order traversal");
bt.showBTree();
System.out.println("Removing data........");
bt.removeNode(138); bt.removeNode(50); bt.removeNode(43);
bt.removeNode(130); bt.removeNode(136); bt.removeNode(41);
bt.removeNode(59); bt.removeNode(54); bt.removeNode(122);
bt.removeNode(124);
System.out.println("Removing task has been completed, now printing B-Tree");
bt.showBTree();
*/