Gettysburg College

CS 216
Data Structures

Spring 2024

Assignment 9

Due: Mon, Apr 15, by 11:59pm
  • method stubs: Node|BTree.java
  • junit tests: BTreeTest.java
  • coverage-Node.pdf
  • coverage-BTree.pdf
  • api-BTree.pdf (ony for BTree.java)
Due: Thu, Apr 18, by 11:59pm
  • Node|BTree.java
  • BTreeTest.java
  • coverage-Node.pdf
  • coverage-BTree.pdf

Preliminaries

Implement the B-Tree data structure which supports the methods given below.

Create project BTree that has class BTree. All classes for this assignment should be put in separate files. Unlike the previous assignments, class Node should be generic and should always be referred to as Node<E> in the code.

Make use of the following List methods where appropriate:

indexOf | get(index) | add(index) | getLast | addLast | addAll

Visualization resources

Here is a useful visualization resource:

JUnit

Copy to your Tester the contents of the following file and make the relevant updates/changes:

BTreeTest.java

See method toString at the end for the expected string format.

The style and general expectations are the same as in Assignments 5 and 6.

Node Class (Part I: Add, Contains, Inorder)

Make this an external, generic class (unlike the Nodes for BSTree and DLinkedList, which were internal classes).

The Node class has the following data members:

The Node class has the following methods:

Node(int theOrder, Comparator<E> theComp)

Creates an empty node of the given order and the given comparator.
Node(int theOrder, Comparator<E> theComp, Node<E> left, E item, Node<E> right)

Creates a node with the given left and right children and the single separator data item for the children.

Don't forget to ... .

Node(int theOrder, Comparator<E> theComp, Node<E> theParent, LinkedList<E> theData, LinkedList<Node<E>> theChildren)

Creates a node with the given parent p, data items, and children.

Don't forget to ... .

boolean hasOverflow()

Determines if this node is filled beyond capacity (and needs to be split).
boolean isLeaf()

Determines if this node is a leaf.
Node<E> childToFollow(E item)

Returns the next child to follow down the tree in order to locate the given item.

[ this is useful for traversing the tree to find the leaf where the item would be inserted ]

Think of the given item as a rolling ball over the items in the node. When the rolling ball hits a larger item, it chooses to go down the arrow/child to the left side of that large item.

void leafAdd(E item)

Inserts the given item in the correct position among this node's data items.

[ this is intended to be used with leaf nodes only; no checks needed ]

void split()

split.png Splits this node by creating a new right sibling node. The new sibling is given half of this node's data items and half of the children. The original middle value of this node is promoted to this node's parent and the new sibling is inserted in this node's parent behind the middle value. No loops.

Mthod indexOf(...) can be used to find the index of this node (the one being split) among its parent's children.

Method subList(int from, int to) can be used to retrieve a portion of a list data structue (check the API for meaning of from and to). Note that you also need to use clear() to remove that portion from the original list.

// transfer a range from one list to another -- copy+clear
myList = new L.L.( yourList.subList(from, to) );
yourList.subList(from, to).clear();
No loops.
boolean contains(E item)

Determines if this node contains the given item.

BTree Class (Part I: Add, Contains)

The BTree class has the following data members:

The BTree class has the following methods:

BTree(int theOrder, Comparator<E> theComp)

Creates an empty tree of the given order and the given comparator.
void add(E item)

Adds the given item to the tree. See INSERT Algorithm below.

Node<E> findLeaf(Node<E> curr, E item)

(non-recursive) Finds the leaf node in the tree rooted at the given node curr where the given item should be inserted.
boolean contains(E item)

Determines if the tree contains the given item (see findNode).
Node<E> findNode(Node<E> curr, E item)

(recursive) Finds the node that contains the given item in the tree rooted at the given node curr.
void inorder(Visitor<E> visitor)

Performs inorder traversal of this tree (see next method). Recall that inorder traversal visits the items in sorted order.

Test this method similar to how it was tested in Assignment 6. Use StringVisitor and recall that inorder will list the items in sorted order.

void inorder(Visitor<E> visitor, Node<E> curr)

(recursive) Performs inorder traversal of the tree rooted at the given node curr.

This is a generalization of the inorder traversal of a BSTree:

  • for BSTree the inorder traversal was:

    traverse child 1 (the left), visit item, traverse child 2 (the right)

  • for BTree the inorder traversal is:

    traverse child 1, visit item 1, traverse child 2, visit item 2, traverse child 3, .... and so on

String toStringSorted()

Returns a string representation of this tree in sorted order.

This method simply calls void inorder(Visitor<E> visitor) with the StringVisitor from Assignment 6 (copy relevant classes to this project).

Tree with L=4:                       String representation:
   
     [ 10      20 ]                  [5 8 10 12 18 20 23 36 40]
     /      |      \                 
[5 8]    [12 18]  [23 36 40]
String toString()

Returns a string representation of this tree in level-order traversal in this format:

Tree with L=4:                       String representation:
   
     [ 10      20 ]                  [[10 20] [5 8] [12 18] [23 36 40]]
     /      |      \                  -lvl=1- ---------lvl=2---------- ---etc.---
[5 8]    [12 18]  [23 36 40]
Adapt the BSTree Level Order Iterator from Assignment 5. Recall that we discussed a while-loop version of BSTree Level Order that was then split in pieces, which were put in various iterator methods.

Here we put those pieces back together into the loop method. Conceptually, the main difference between B-Tree and BStree is that we insert many children in the queue at each step, not just two. Essentially allmost all of the code from the iterator is placed directly here, in method toString, with appropriate changes.

Only one loop. Note that you can write:

str = str + list_of_stuff;

To remove the commas at the end:

str = str.replaceAll(",", "")

INSERT Algorithm

Here is the pseudocode for the BTree class INSERT operation:
  1. find the leaf node where the item should be inserted

  2. add the item to the leaf node

  3. start from the leaf node moving up towards the root

  4. as long as current node is full, split current node and move up

  5. final adjustments, if necessary