Add BTree skeleton project and pdf

This commit is contained in:
rec0de 2018-05-23 10:26:44 +02:00
parent 58bd1921bf
commit b0784f990f
9 changed files with 797 additions and 0 deletions

BIN
BTree/Lab3-en.pdf Normal file

Binary file not shown.

22
BTree/TestFile1.txt Normal file
View File

@ -0,0 +1,22 @@
E465L;ZPOE;OK
JZXHZ;FCB6;Error
FMF1Q;TZ0Q;Error
KC83O;JVA8;Error
NXM6F;6UWJ;Error
VM22T;8ESM;Error
L2Z74;99YH;Error
DP56R;7OTD;OK
YMUEM;9LVC;Error
14ST0;1GLP;OK
8ENSQ;EGV9;OK
HRR27;B6JY;Error
IUS3K;395W;OK
GFV8X;4TT0;Error
4OVZB;RS9F;OK
9BTCH;8AHW;Error
319BC;WVH9;OK
W0KBB;1RE7;Error
OTYAH;43JX;Error
SSG24;YXB1;Error
U36TU;Q5NO;Error
TY4L8;P0D3;OK

View File

@ -0,0 +1,383 @@
package frame;
/**
* B_TreeTestCase
*
* Version: 1.0
*
*
*/
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import lab.B_Tree;
/**
* TestCases for the third lab.
*
*/
@DisplayName("B-Tree tests")
public class AllTests {
protected ArrayList<TestNode> nodes = new ArrayList<TestNode>();
protected ArrayList<String> node_names = new ArrayList<String>();
protected ArrayList<String> pointers = new ArrayList<String>();
protected void testNode(String name, TestNode t, int n_e, int n_ch, String ent) {
assertEquals(n_e, t.getEntries().size(), "Number of entries of " + name + " not correct!");
assertEquals(n_ch, t.getChildren().size(), "Number of childen of " + name + " not correct!");
assertEquals(ent, t.entriesToString(), "Entries of " + name + " not correct!");
}
protected void testNode(String name, TestNode t, int n_e, int n_ch, String ent, int n_e2, int n_ch2, String ent2) {
boolean t1 = (t.getEntries().size() == n_e || t.getEntries().size() == n_e2);
boolean t2 = (t.getChildren().size() == n_ch || t.getChildren().size() == n_ch2);
boolean t3 = (t.entriesToString().equalsIgnoreCase(ent) || t.entriesToString().equalsIgnoreCase(ent2));
assertTrue(t1, "Number of entries of " + name + " not correct!");
assertTrue(t2, "Number of childen of " + name + " not correct!");
assertTrue(t3, "Entries of " + name + " not correct!");
}
protected boolean testOrderOfEntries(ArrayList<Entry> e) {
for (int i = 0; i < e.size() - 1; i++) {
if (e.get(i).compareTo(e.get(i + 1)) >= 0) {
return false;
}
}
return true;
}
protected void parseB_Tree(ArrayList<String> output, int k, String name) {
int i = 0;
int noChildren = 0;
String line;
while (i < output.size()) {
line = output.get(i);
/**
* only progress if the word "Digraph" and "}" is not contained in the line.
* "Digraph" is only contained in the first and "}" only in the last line.
*/
if (!line.contains(DotFileConstants.DOT_FILE_DIGRAPH)
&& !line.contains(DotFileConstants.DOT_FILE_CLOSE_BRACKET)
&& !line.contains(DotFileConstants.DOT_FILE_SOURCE)) {
// progress a node
if (line.contains(DotFileConstants.DOT_FILE_LABEL_START) && line.startsWith(name + "[")) {
progressNode(line, k);
}
// progress a pointer
else if (line.contains(DotFileConstants.DOT_FILE_EDGE) && line.startsWith(name + ":")) {
noChildren++;
progressPointer(line);
}
}
i++;
}
if (noChildren > 0) {
String[] temp = new String[noChildren];
int lastIndex = pointers.size() - 1;
for (int j = 0; j < noChildren; j++) {
String[] p = pointers.get(lastIndex - j).split("->");
String number = ((p[0].split(":"))[1]).split("f")[1];
int no = Integer.valueOf(number);
temp[no / 2] = p[1];
}
for (int j = 0; j < noChildren; j++) {
parseB_Tree(output, k, temp[j]);
}
}
}
protected void progressNode(String line, int k) {
TestNode result = new TestNode(k);
String[] names = line.split("\\[");
String[] entries = (line.split("\""))[1].split("\\|?+<f[0-9]+>\\*?+\\|?+");
for (int i = 0; i < entries.length; i++) {
if (!entries[i].equals("")) {
Entry e = new Entry();
e.setKey(entries[i]);
result.addEntry(e);
}
}
node_names.add(names[0].trim());
nodes.add(result);
}
protected void progressPointer(String line) {
String pointer = (line.split(";"))[0];
pointers.add(pointer.trim());
}
protected ArrayList<TestNode> constractB_Tree(ArrayList<String> output) {
ArrayList<TestNode> r = new ArrayList<TestNode>();
parseB_Tree(output, 2, "root");
Collections.sort(pointers);
TestNode root = nodes.get(node_names.indexOf("root"));
ArrayList<String> pts = new ArrayList<String>();
for (int i = 0; i < pointers.size(); i++) {
String[] p = pointers.get(i).split("->");
String parent = (p[0].split(":"))[0];
pts.add(parent.trim());
pts.add(p[1].trim());
}
for (int i = 0; i < pts.size(); i = i + 2) {
nodes.get(node_names.indexOf(pts.get(i))).addChild(nodes.get(node_names.indexOf(pts.get(i + 1))));
}
r.add(root);
int i = 0;
while (i < r.size()) {
r.addAll(r.get(i).getChildren());
i++;
}
return r;
}
private void printArrayList(ArrayList<String> dot) {
try {
FileWriter fw = new FileWriter("test.txt");
BufferedWriter bw = new BufferedWriter(fw);
for (String string : dot) {
bw.write(string + System.getProperty("line.separator"));
System.out.println(string);
}
bw.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
protected boolean isBalanced(TestNode t) {
return getBalancedHeight(t) > -1;
}
/**
* @param t
* the root of the checked subtree
* @return -1 if the subtree isnt balanced, and the height of the subtree, if it
* is.
*/
protected int getBalancedHeight(TestNode t) {
ArrayList<TestNode> children = t.getChildren();
if (children.isEmpty())
return 0;
int height = getBalancedHeight(children.get(0));
for (TestNode child : children) {
if (height != getBalancedHeight(child))
return -1;
}
return (height == -1) ? -1 : height + 1;
}
@Nested
@DisplayName("Insert tests")
class B_TreeInsertTests {
@Test
@DisplayName("Number of Nodes")
public void testInsertFile1_NumberOfNodes() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
ArrayList<String> out = b.getB_Tree();
ArrayList<TestNode> test_tree = constractB_Tree(out);
assertEquals(14, test_tree.size(), "Number of nodes not correct!");
}
@Test
@DisplayName("Height of Tree")
public void testInsertFile1_HeightOfTree() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
assertEquals(2, b.getB_TreeHeight(), "Height of the tree not correct!");
}
@Test
@DisplayName("Number of Entries")
public void testInsertFile1_NumberOfEntries() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
assertEquals(22, b.getB_TreeSize(), "Number of the entries is not correct!");
}
@Test
@DisplayName("Nodes of Tree")
public void testInsertFile1_NodesOfTree() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
ArrayList<String> out = b.getB_Tree();
constractB_Tree(out);
testNode("root", nodes.get(0), 3, 4, "FMF1QTZ0QKC83OJVA8SSG24YXB1");
testNode("node" + 1, nodes.get(1), 2, 3, "4OVZBRS9FDP56R7OTD");
testNode("node" + 2, nodes.get(2), 2, 0, "14ST01GLP319BCWVH9");
testNode("node" + 3, nodes.get(3), 2, 0, "8ENSQEGV99BTCH8AHW");
testNode("node" + 4, nodes.get(4), 1, 0, "E465LZPOE");
testNode("node" + 5, nodes.get(5), 1, 2, "IUS3K395W");
testNode("node" + 6, nodes.get(6), 2, 0, "GFV8X4TT0HRR27B6JY");
testNode("node" + 7, nodes.get(7), 1, 0, "JZXHZFCB6");
testNode("node" + 8, nodes.get(8), 1, 2, "NXM6F6UWJ");
testNode("node" + 9, nodes.get(9), 1, 0, "L2Z7499YH");
testNode("node" + 10, nodes.get(10), 1, 0, "OTYAH43JX");
testNode("node" + 11, nodes.get(11), 1, 2, "W0KBB1RE7");
testNode("node" + 12, nodes.get(12), 3, 0, "TY4L8P0D3U36TUQ5NOVM22T8ESM");
testNode("node" + 13, nodes.get(13), 1, 0, "YMUEM9LVC");
}
@Test
@DisplayName("Order of Entries")
public void testInsertFile1_InOrderTraversal() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
assertTrue(testOrderOfEntries(b.getInorderTraversal()),
"getInorderTraversal() doesn't deliver entries in inorder traversal!");
}
@Test
@DisplayName("Balance of Tree")
public void testInsertFile1_Balanced() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
ArrayList<String> out = b.getB_Tree();
ArrayList<TestNode> test_tree = constractB_Tree(out);
assertTrue(isBalanced(test_tree.get(0)), "The Tree is not balanced!");
}
}
@Nested
@DisplayName("Delete tests")
class B_TreeDeleteTests {
@Test
@DisplayName("Returned Entries")
public void testDeleteFile1_ReturnedEntries() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
Entry e1 = b.delete("L2Z7499YH");
Entry e2 = b.delete("FMF1QTZ0Q");
Entry e3 = b.delete("L2Z74TZ0Q");
assertEquals("L2Z74;99YH;Error", e1.toString(), "delete(L2Z7499YH) output not correct!");
assertEquals("FMF1Q;TZ0Q;Error", e2.toString(), "delete(FMF1QTZ0Q) output not correct!");
assertTrue(null == e3, "delete(L2Z74TZ0Q) output not correct!");
}
@Test
@DisplayName("Number of Nodes")
public void testDeleteFile1_NumberOfNodes() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
b.delete("L2Z7499YH");
b.delete("FMF1QTZ0Q");
b.delete("L2Z74TZ0Q");
ArrayList<String> out = b.getB_Tree();
ArrayList<TestNode> test_tree = constractB_Tree(out);
assertEquals(12, test_tree.size(), "Number of nodes not correct!");
}
@Test
@DisplayName("Height of Tree")
public void testDeleteFile1_HeightOfTree() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
b.delete("L2Z7499YH");
b.delete("FMF1QTZ0Q");
b.delete("L2Z74TZ0Q");
assertEquals(2, b.getB_TreeHeight(), "Height of the tree not correct!");
}
@Test
@DisplayName("Number of Entries")
public void testDeleteFile1_NumberOfEntries() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
b.delete("L2Z7499YH");
b.delete("FMF1QTZ0Q");
b.delete("L2Z74TZ0Q");
b.getB_Tree();
assertEquals(20, b.getB_TreeSize(), "Number of the entries is not correct!");
}
@Test
@DisplayName("Nodes of Tree")
public void testDeleteFile1_NodesOfTree() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
b.delete("L2Z7499YH");
b.delete("FMF1QTZ0Q");
b.delete("L2Z74TZ0Q");
ArrayList<String> out = b.getB_Tree();
constractB_Tree(out);
testNode("root", nodes.get(0), 2, 3, "E465LZPOESSG24YXB1", 2, 3, "GFV8X4TT0SSG24YXB1");
testNode("node" + 1, nodes.get(1), 2, 3, "4OVZBRS9F9BTCH8AHW", 2, 3, "4OVZBRS9FDP56R7OTD");
testNode("node" + 2, nodes.get(2), 2, 0, "14ST01GLP319BCWVH9");
testNode("node" + 3, nodes.get(3), 1, 0, "8ENSQEGV9", 2, 0, "8ENSQEGV99BTCH8AHW");
testNode("node" + 4, nodes.get(4), 1, 0, "DP56R7OTD", 1, 0, "E465LZPOE");
testNode("node" + 5, nodes.get(5), 2, 3, "IUS3K395WNXM6F6UWJ");
testNode("node" + 6, nodes.get(6), 2, 0, "GFV8X4TT0HRR27B6JY", 1, 0, "HRR27B6JY");
testNode("node" + 7, nodes.get(7), 2, 0, "JZXHZFCB6KC83OJVA8");
testNode("node" + 8, nodes.get(8), 1, 0, "OTYAH43JX");
testNode("node" + 9, nodes.get(9), 1, 2, "W0KBB1RE7");
testNode("node" + 10, nodes.get(10), 3, 0, "TY4L8P0D3U36TUQ5NOVM22T8ESM");
testNode("node" + 11, nodes.get(11), 1, 0, "YMUEM9LVC");
}
@Test
@DisplayName("Order of Entries")
public void testDeleteFile1_InOrderTraversal() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
b.delete("L2Z7499YH");
b.delete("FMF1QTZ0Q");
b.delete("L2Z74TZ0Q");
assertTrue(testOrderOfEntries(b.getInorderTraversal()),
"getInorderTraversal() doesn't deliver entries in inorder traversal!");
}
@Test
@DisplayName("Balance of Tree")
public void testDeleteFile1_Balanced() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
b.delete("L2Z7499YH");
b.delete("FMF1QTZ0Q");
b.delete("L2Z74TZ0Q");
ArrayList<String> out = b.getB_Tree();
ArrayList<TestNode> test_tree = constractB_Tree(out);
assertTrue(isBalanced(test_tree.get(0)), "The Tree is not balanced!");
}
}
@Nested
@DisplayName("Find tests")
class B_TreeFindTests {
@Test
@DisplayName("Returned Entries")
public void testfindFile1_ReturnedEntries() {
B_Tree b = new B_Tree(2);
b.constructB_TreeFromFile("TestFile1.txt");
Entry e1 = b.find("SSG24YXB1");
Entry e2 = b.find("SSG27YXB1");
assertEquals("SSG24;YXB1;Error", e1.toString(), "find(SSG24YXB1) output not correct!");
assertTrue(null == e2, "find(SSG27YXB1) output not correct!");
}
}
}

View File

@ -0,0 +1,59 @@
package frame;
/**
* DotFileConstants.java
*
* Version: 1.0
*/
/**
* Holds constant Strings for formatting the output to the dot-format.
*
*/
public class DotFileConstants {
//basic Strings
/** String for the dot-file format indicating a graph. */
public static final String DOT_FILE_DIGRAPH = "digraph";
/** String for the dot-file format indicating the start of a structure.*/
public static final String DOT_FILE_OPEN_BRACKET = "{";
/** String for the dot-file format indicating the end of a structure.*/
public static final String DOT_FILE_CLOSE_BRACKET = "}";
/** The start String for a dot-file. */
public static final String DOT_FILE_START = DOT_FILE_DIGRAPH + " "
+ DOT_FILE_OPEN_BRACKET;
/** The end String for a dot-file. */
public static final String DOT_FILE_END = "}";
/** String for the dot-file format seperating numbers. */
public static final String DOT_FILE_DASH = "-";
/** String for the dot-file format starting a label. */
public static final String DOT_FILE_LABEL_START = "label";
/** String for the dot-file format ending a label. */
public static final String DOT_FILE_LABEL_END = "\"]";
//edge Strings
/** String for the dot-file format indicating an edge. */
public static final String DOT_FILE_EDGE = "->";
/** String for the dot-file format indicating a bold style. */
public static final String DOT_FILE_MARKUP = "[style=bold]";
/** String for the dot-file format indicating a source. */
public static final String DOT_FILE_SOURCE = "[shape=record]";
/** String for the dot-file format indicating sink. */
public static final String DOT_FILE_DESTINATION = "[shape=circle]";
/** String for the dot-file format ending a line. */
public static final String DOT_FILE_LINE_END = ";";
//output file Strings
/** A String for the output file name. */
public static final String DOT_FILE_FROM = "from";
/** A String for the output file name. */
public static final String DOT_FILE_TO = "to";
/** A String for the output file name. */
public static final String DOT_FILE_DISTANCE = "distance";
/** A String for the output file name. */
public static final String DOT_FILE_TIME = "time";
}

View File

@ -0,0 +1,63 @@
package frame;
/*
* Entry.java
*
*/
public class Entry implements EntryInterface, Comparable<Entry> {
private String key;
private String data;
/** Creates a new instance of Entry */
public Entry() {
this.key = null;
this.data = null;
}
public Entry(String bookSerialNumber, String ReaderID, String Status) {
this.key = new String(bookSerialNumber.concat(ReaderID));
this.data = new String(Status);
}
public void setKey(String newKey) {
this.key = new String(newKey);
}
public void setData(String newData) {
this.data = new String(newData);
}
public String getKey() {
if(this.key != null) {
return this.key;
} else {
return null;
}
}
public String getData() {
if(this.data != null) {
return this.data;
} else {
return null;
}
}
public String toString() {
String r = new String();
if (this.key != null) {
r = this.key.substring(0, 5) + ";" + this.key.substring(5);
}
if(this.data != null) {
r = r + ";" + this.data;
}
return r;
}
public int compareTo(Entry e) {
return this.key.compareTo(e.getKey());
}
}

View File

@ -0,0 +1,14 @@
package frame;
/*
* EntryInterface.java
*
*/
public interface EntryInterface {
void setKey(String newKey);
void setData(String newData);
String getKey();
String getData();
String toString();
}

View File

@ -0,0 +1,43 @@
package frame;
/*
* TestNode.java
*
*/
import java.util.ArrayList;
public class TestNode {
private ArrayList<Entry> nodeEntries; //stored entries in the node
private ArrayList<TestNode> children; //pointers to the children nodes
/** Creates a new instance of TestNode */
public TestNode(int t) {
this.nodeEntries = new ArrayList<Entry>(2*t-1);
this.children = new ArrayList<TestNode>(2*t);
}
public void addEntry(Entry e) {
nodeEntries.add(e);
}
public void addChild(TestNode b) {
children.add(b);
}
public ArrayList<Entry> getEntries() {
return this.nodeEntries;
}
public String entriesToString() {
String r = new String();
for(int i=0;i<nodeEntries.size();i++) {
r = r + nodeEntries.get(i).getKey();
}
return r;
}
public ArrayList<TestNode> getChildren() {
return this.children;
}
}

180
BTree/src/lab/B_Tree.java Normal file
View File

@ -0,0 +1,180 @@
package lab;
import java.util.ArrayList;
import frame.*;
/*
* Implements a B-Tree structure as introduced in the
* lecture to store the information read by the RFID
* readers in the library.
*
* Make sure that you have tested all the given test cases
* given on the homepage before you submit your solution.
*
*/
public class B_Tree {
/**
* The constructor
*
* @param t minimum degree of the B-tree.
* t can not be changed once a new B Tree object is created.
*
*/
public B_Tree(int t) {
/**
* Add your code here
*/
}
/**
* This method takes as input the name of a file containing a sequence of
* entries that should be inserted to the B-Tree in the order they appear in
* the file. You cannot make any assumptions on the order of the entries nor
* is it allowed to change the order given in the file. You can assume that the
* file is located in the same directory as the executable program. The input
* file is similar to the input file for lab 1. The return value is the number of
* entries successfully inserted in the B-Tree.
*
* @param filename name of the file containing the entries
* @return returns the number of entries successfully inserted in the B-Tree.
*/
public int constructB_TreeFromFile (String filename) {
/**
* Add your code here
*/
return 0;
}
/**
* This method inserts the entry insertEntry into the B-Tree. Note that you
* have to deal with overflows if you want to insert an entry into a leaf which
* already contains 2t - 1 entries. This method returns true if the insertion
* of the entry insertEntry is successful and false if the key of this entry
* already exists in the B-Tree.
*
* @param insertEntry entry to insert into the B-Tree
* @return returns true if the entry insertEntry is successfully inserted
* false if the entry already exists in the B-Tree
*/
public boolean insert(Entry insertEntry) {
/**
* Add your code here
*/
return true;
}
/**
* This method deletes the entry from the B-Tree structure, having deleteKey
* as key. In this method you have to distinguish between two cases:
* 1. The entry, having deleteKey as key, is located in an internal node.
* 2. The entry, having deleteKey as key, is located in a leaf.
* This method returns the entry, having deleteKey as key if the deletion is
* successful and null if the key deleteKey is not found in any entry of the
* B-Tree.
*
* @param deleteKey key of the entry to delete from the B-Tree
* @return returns the deleted entry if the deletion ends successfully
* null if the entry is not found in the B-Tree
*/
public Entry delete(String deleteKey) {
/**
* Add your code here
*/
return new Entry();
}
/**
* This method searches in the B-Tree for the entry with key searchKey. It
* returns the entry, having searchKey as key if such an entry is found, null
* otherwise.
*
* @param searchKey key of the entry to find in the B-Tree
* @return returns the entry having searchKey as key if such an entry exists
* null if the entry is not found in the B-Tree
*/
public Entry find(String searchKey) {
/**
* Add your code here
*/
return new Entry();
}
/**
* This method returns a ArrayList<String> containing the output B-Tree.
* The output should be directly interpretable dot code.
* Each item in the ArrayList corresponds to one line of the output
* tree. The nodes of the output tree should only
* contain the keys of the entries and not the data.
*
* @return returns the output B-Tree in directly interpretable dot code
*/
public ArrayList<String> getB_Tree() {
/**
* Add your code here
*/
return new ArrayList<>();
}
/**
* This method returns the height of the B-Tree
* If the B-Tree is empty this method should return 0.
*
* @return returns the height of the B-Tree
*/
public int getB_TreeHeight() {
/**
* Add your code here
*/
return 0;
}
/**
* This method traverses the B-Tree in inorder and adds each entry to a
* ArrayList<Entry>. The returned ArrayList contains the entries of the B-Tree
* in ascending order.
*
* @return returns the entries stored in the B-Tree in ascending order
*/
public ArrayList<Entry> getInorderTraversal() {
/**
* Add your code here
*/
return new ArrayList<>();
}
/**
* This method returns the number of entries in the B-Tree (not the number
* of nodes).
*
*
* @return returns the size of the B-Tree, i.e., the number of entries stored in the B-Tree
*/
public int getB_TreeSize() {
/**
* Add your code here
*/
return 0;
}
}

View File

@ -0,0 +1,33 @@
package lab;
/*
* Implements a node of a B-Tree
*
* Make sure that you have tested all the given test cases
* given on the homepage before you submit your solution.
*
*/
public class B_TreeNode {
/**
* The constructor
*
* @param t minimum degree of the B-tree
*
*/
public B_TreeNode(int t) {
/**
* Add your code here
*/
}
/**
* Add your code here
*/
}