Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 110
at HeapPriorityQueue.hasLeft(HeapPriorityQueue.java:168)
at HeapPriorityQueue.bubbleDown(HeapPriorityQueue.java:111)
at HeapPriorityQueue.removeMin(HeapPriorityQueue.java:73)
at a4tester.testRandomArray(a4tester.java:224)
at a4tester.stressTest(a4tester.java:237)
at a4tester.main(a4tester.java:283)
I have been trying to find where the Out of bounds exception is coming from and it is driving me insane! It only arises when my HeapPriorityQueue is put through the stress test below.
Basically getting an array out of bounds exception when my code is ran through this stress test:
public static boolean testRandomArray (int count) {
PriorityQueue q = createNewPriorityQueue(count);
System.out.println("Testing size: " + count);
Random r = new Random();
for ( int i = 0; i < count; i++ )
{
int val = r.nextInt(1000000);
q.insert (val);
}
int oldVal = -1;
while (!q.isEmpty() )
{
int val = (int)((Integer)q.removeMin()).intValue(); // or a bug
if ( oldVal > val )
return false;
oldVal = val;
}
return true;
}
This is my Program:
public class HeapPriorityQueue implements PriorityQueue {
protected final static int DEFAULT_SIZE = 10000;
/* This array is where you will store the elements in the heap */
protected Comparable storage[];
/* Keep track of the current number of elements in the heap */
protected int currentSize;
/* You do not need to change this constructor */
public HeapPriorityQueue ()
{
this(DEFAULT_SIZE);
}
/* You do not need to change this constructor */
public HeapPriorityQueue(int size)
{
storage = new Comparable[size + 1];
currentSize = 0;
}
/*
* You need to change the implementation of every public method
* below this comment.
*
*/
public int size () {
return currentSize;
}
public boolean isEmpty () {
if(size() == 0)
return true;
return false;
}
public Comparable removeMin () throws HeapEmptyException {
if(isEmpty())
throw new HeapEmptyException();
Comparable returnValue = storage[1];
storage[1] = storage[currentSize];
storage[currentSize] = null;
currentSize--;
bubbleDown();
return returnValue;
}
public void insert ( Comparable k ) throws HeapFullException {
if(currentSize >= storage.length - 1)
throw new HeapFullException();
currentSize++;
storage[currentSize] = k;
bubbleUp();
}
/* Your instructor's solution used the following helper methods
*
* You do not need to use the same methods, but you may want to.
*/
/*
* A new value has just been added to the bottom of the heap
* "bubble up" until it is in the correct position
*/
private void bubbleUp () {
int index = currentSize;
while(parent(index) != 0 && storage[parent(index)].compareTo(storage[index]) > 0) {
swapElement(index, parent(index));
index = parent(index);
}
}
/*
* Because of a removeMin operation, a value from the bottom
* of the heap has been moved to the root.
*
* "bubble down" until it is in the right position
*/
private void bubbleDown() {
int index = 1;
while (hasLeft(index)) {
int sc = leftChild(index);
if (hasRight(index) && storage[leftChild(index)].compareTo(storage[rightChild(index)]) > 0) {
sc = rightChild(index);
}
if (storage[index].compareTo(storage[sc]) > 0) {
swapElement(index, sc);
}
else{
}
index = sc;
}
}
/*
* Swap the element at position p1 in the array with the element at
* position p2
*/
private void swapElement ( int p1, int p2 ) {
Comparable temp = storage[p1];
storage[p1] = storage[p2];
storage[p2] = temp;
}
/*
* Return the index of the parent of the node at pos
*/
private int parent ( int pos )
{
return (pos/2); // replace this with working code
}
/*
* Return the index of the left child of the node at pos
*/
private int leftChild ( int pos )
{
return (pos*2); // replace this with working code
}
/*
* Return the index of the right child of the node at pos
*/
private int rightChild ( int pos )
{
return (pos * 2)+1; // replace this with working code
}
/*
* Given the current number of elements in the heap, does the
* node at pos have a left child?
*
* Note that all internal nodes have at least a left child.
*
*/
private boolean hasLeft ( int pos )
{
if(storage[leftChild(pos)] != null)
return true;
return false; // replace this with working code
}
/*
* Given the current number of elements in the heap, does the
* node at pos have a right child?
*/
private boolean hasRight ( int pos ) {
if(storage[rightChild(pos)] != null)
return true;
return false; // replace this with working code
}
}
There are a few things that are potentially problematic:
private boolean hasLeft ( int pos )
{
if(storage[leftChild(pos)] != null)
return true;
return false; // replace this with working code
}
should be changed to something like:
private boolean hasLeft ( int pos )
{
if (storage.length > leftChild(pos) && storage[leftChild(pos)] != null)
return true;
return false; // replace this with working code
}
since you could be going out of bounds in your original code. The same logic applies to hasRight(). Additionally, you're also attempting to access storage, but you're never checking its length, ie you have storage[1], but there's not guarantee that you didn't pass 0 to your constructor. Hope that helps.
Related
I have implemented a binary search tree. Most of my test in JUNIT test is going through, including these two. I have implementedleavesIsCorrectWhenTreeIsPerfect() and insertValuesInAscendingOrderIncrementsHeight().
Both of these test goes through, however i do not know if it is correctly written based on what their description is asking.
//EDIT: I have added a test that might be a help to one of the test a need help with.
//TODO: help me understand if I have written the correct code for the test in insertValuesInAscendingOrderIncrementsHeight() and leavesIsCorrectWhenTreeIsPerfect() based on what the description for the test is saying.
Have in mind, that I have not included all the tests in the test class, Because the goes through with my implementation of the tree.
Down here I have included my tree class and the test class with both the test I need help with.
/**
* An Binary Search tree implementation.
* #param <T>
*/
public class Tree <T extends Comparable <T>> implements BSTInterface <T>{
private int size;
private Node root;
public class Node{
private Node Left;
private Node Right;
private T data;
public Node(T data){
this.data = data;
}
public Node getRight(){
return Right;
}
public Node getLeft() {
return Left;
}
public T getData() {
return data;
}
}
public Tree (){
size = 0;
root = null;
}
/**
* Test for presence of a value.
* #param elem
* #return true/false
*/
#Override
public boolean search(T elem) {
if(root == null ||elem == null){
return false;
}
Node node = root;
while(true){
if(node.data.compareTo(elem) > 0){
if(node.Right == null){
return false;
} else{
node = node.Right;
}
} else if(node.data.compareTo(elem) == 0){
break;
} else{
if(node.Left== null){
return false;
}
else{
node = node.Left;
}
}
}
return true;
}
/**
* Add value to tree; duplicates are not allowed.
* Return true if the element is not already present (and is thus inserted),
* false otherwise.
*
* #param elem
* #return true/false
*/
#Override
public boolean insert(T elem) {
if (elem == null){
return false;
}
if (root == null){
root = new Node(elem);
size++;
return true;
}
Node node = root;
while (true){
if (node.data.compareTo(elem) > 0) {
if (node.Right == null){
node.Right = new Node(elem);
size++;
break;
} else {
node = node.Right;
}
} else if (node.data.compareTo(elem) == 0) {
return false;
} else {
if (node.Left == null){
node.Left = new Node(elem);
size++;
break;
} else {
node = node.Left;
}
}
}
return true;
}
/**
* the number of elements in the tree
* #return size.
*/
#Override
public int size() {
return size;
}
/**
* The height of the tree.
* The empty tree and the tree with only the root node both have height 0.
* #return the height of the tree.
*/
#Override
public int height() {
return countHeight(root);
}
/**
* Helper method for height
*/
private int countHeight(Node node){
if(node == null) {
return 0;
}
if (node.Left == null && node.Right == null) {
return 0;
}
return 1 + Math.max(countHeight(node.getLeft()), countHeight(node.getRight()));
}
/**
* The number of leaves in the tree.
* #return the amount of leaves the tree has.
*/
#Override
public int leaves() {
return countLeaves(root);
}
/**
* Helper method for leaves
*/
private int countLeaves(Node node) {
if (node == null) {
return 0;
}
if (node.Left == null && node.Right == null) {
return 1;
}
return countLeaves(node.Left) + countLeaves(node.Right);
}
/**
* A string describing the tree
* #return
*/
public String toString(){
String str = "[" + helpToString(root);
if (str.length() > 1) {
str = str.substring(0, str.length() - 2);
} return str + "]";
}
/**
* Helper method for toString
*/
private String helpToString(Node node) {
String str = "";
if (node != null) {
str += helpToString(node.Right);
str += node.data + ", ";
str += helpToString(node.Left);
}
return str;
}
}
import org.junit.Test;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.Timeout;
import static org.junit.Assert.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import java.util.Arrays;
import java.util.stream.IntStream;
/**
* Test class for a tree.
*/
public class TreeTest{
#Rule public Timeout globalTimeout = Timeout.seconds(5);
Tree<Integer> tree;
int[] elementsInTree;
int[] elementsNotInTree;
#Before
public void setUp() {
/**
* This tree should look like this:
*
* 8
* / \
* 3 10
* / \ \
* 1 6 14
* / \ /
* 4 7 13
*/
tree = new Tree<>();
elementsInTree = new int[] {8, 10, 14, 13, 3, 1, 6, 4, 7};
for (int elem : elementsInTree) {
tree.insert(elem);
}
elementsNotInTree = new int[] {34, -3, -10, 12, 74, 5};
}
#Test
public void heightIsLogOfNumLeavesTreeIsPerfect() {
// For a perfect tree, tree.height() == log2(tree.leaves()
// Arrange
Tree<Integer> tree = new Tree<>();
int[] elements = new int[] {8, 3, 10, 1, 6, 9, 14};
int numLeaves = 4;
int logNumLeaves = (int) Math.round(Math.log(numLeaves) / Math.log(2));
for (int elem : elements) {
tree.insert(elem);
}
// Act
int height = tree.height();
// Assert
assertThat(height, equalTo(logNumLeaves));
}
#Test
public void leavesIsCorrectWhenTreeIsPerfect() { //TEST
// A perfect tree has all leaves at the same depth, and all internal nodes
// (i.e. non-leaves) have two children
//
// This test should assert that a perfect tree with 2*n-1 nodes total,
// has exactly n leaves (i.e. that Tree.leaves() returns n).
//
// An example is the perfect three-node tree from the test above:
//
// (1338)
// / \
// (1337) (1396)
// You have to construct your own tree here, with n >= 4
Tree <Integer> tree = new Tree<>();
int n = 4;
for(int i = 0; i>=n; i++) {
tree.insert(i);
int numLeaves = 2*n-1;
int leaves = tree.leaves();
assertThat(leaves,equalTo(numLeaves));
}
}
// Tests for insert/height
#Test
public void insertValuesInAscendingOrderIncrementsHeight() { //TEST
// When inserting elements in ascending order, each element is inserted
// to the right of the deepest node, so the height should increment by
// 1 for each element inserted.
Tree <Integer> tree = new Tree<>();
int val = 100;
for(int i = 0; i < val; i++){
tree.insert(i);
}
int treeHeight = tree.height();
treeHeight++;
assertThat(tree.size(),equalTo(treeHeight));
}
}
for(int i = 0; i>=n; i++) {
tree.insert(i);
The condition of your for loop is always false.
It's awkward that "n" is used in the instructions to describe a tree with n leaves because "n" is traditionally used to describe your node count. But picture a tree with 4 nodes at the bottom, then half that for the prior layer, then half again for the first layer, and you have a tree with 1+2+4 nodes, or 7 nodes total, which coincides with the formula 2*n-1 (2*4-1=7).
#Test
public void leavesIsCorrectWhenTreeIsPerfect() {
int n=4;
int[] balanced=new int[] {4,2,6,1,3,5,7};
for (int i=0; i<balanced.length; i++) {
tree.insert(balanced[i]);
}
int leaves = tree.leaves();
assertThat(balanced.length,equalTo(2*n-1));
assertThat(leaves,equalTo(n));
}
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 1 year ago.
So, im trying to make a snake and ladders game.
The way im trying to do it is by creating a board which has nodes, the first node (head) will have a node next to it, and this one will have this one as a previous node. This repeats until it gets to the total number of nodes (tha last node doesnt have a next node). The way im trying to make the snakes and ladders is by creating a relation of snakeHead and snakeTail or ladderTop and ladderBottom. I then generate a random number which will represent a specific node on the board but for some reason when i try to create the relation i get a nullPointerException on the method createSnakes, i dont get why this is happening so if someone has an idea of why it happens please tell me. Thanks in advance
public class Board {
private int numRows;
private int numColumns;
private int dimension;
private int numSnakes;
private int numLadders;
private Node head;
private Node tail;
/**
* This is the constructor
* #param numRows
* #param numColumns
*/
public Board(int numRows, int numColumns, int numSnakes, int numLadders) {
this.dimension = numColumns * numRows;
this.numLadders = numLadders;
this.numSnakes = numSnakes;
this.numRows = numRows;
this.numColumns = numColumns;
head = new Node(1);
createBoard(head, 2);
createSnakes(0);
createLadders(0);
}
/**
* This method create board
* #param prev this is the prev node
* #param i this is the counter
*/
private void createBoard(Node prev, int i){
if(i <= dimension){
if(i != dimension) {
Node current = new Node(i);
prev.setNext(current);
current.setPrev(prev);
createBoard(current, i + 1);
} else {
tail = new Node(i);
prev.setNext(tail);
tail.setPrev(prev);
}
}
}
private void createSnakes(int i){
if(i<numSnakes){
int initPosition = getInitPosition();
Node init = get(initPosition,1, head);
int endPosition = (int) (Math.random() * initPosition);
Node end = get(endPosition, 1, head);
if(init.getSnakeTail() == null && init.getSnakeHead() == null && end.getSnakeHead() == null && end.getSnakeTail() == null
&& verifyIntervals(initPosition, endPosition, 1, 0, false, false, false) == false){
init.setSnakeTail(end);
end.setSnakeHead(init);
init.setSnake((char)(i+65));
end.setSnake((char)(i+65));
createSnakes(i + 1);
} else {
createSnakes(i);
}
}
}
private void createLadders(int i){
if(i<numLadders){
int initPosition = getInitPosition();
if(initPosition==0){
createLadders(i);
}
Node init = get(initPosition,1, head);
int rank = dimension-initPosition;
int endPosition = (int) (Math.random()*rank);
if(endPosition==0 || endPosition==dimension){
createLadders(i);
}
Node end = get(endPosition+initPosition, 1, head);
if(i==numLadders){
return;
}
if(init.getSnakeTail() == null && end.getSnakeHead() == null && init.getSnakeHead() == null && end.getSnakeTail() == null
&& init.getLadderTop() == null && end.getLadderBottom() == null && init.getLadderBottom() == null && end.getLadderTop() == null
&& verifyIntervals(initPosition, endPosition, 1, 0, false, false, false) == false) {
init.setLadderTop(end);
end.setLadderBottom(init);
init.setLadder((char) (i + 48));
end.setLadder((char) (i + 48));
createLadders(i + 1);
}
else {
createLadders(i);
}
}
}
public boolean verifyIntervals(int init, int end, int varInitPos, int initPos, boolean initFound, boolean endFound,boolean inInterval){
if(inInterval==true){
return true;
}
if(varInitPos==dimension){
return false;
}
else if(varInitPos<initPos+numRows){
if(init==varInitPos){
initFound=true;
}
if(end==varInitPos){
endFound=true;
}
if(initFound==true && endFound==true){
inInterval=true;
}
return verifyIntervals(init,end,varInitPos+1,initPos,initFound,endFound,inInterval);
}
else{
return verifyIntervals(init,end,varInitPos,initPos+numRows,false,false, false);
}
}
public Node getTail() {
return tail;
}
public Node get(int position, int i, Node current){
if(i == position){
return current;
} else if(i==dimension) {
return null;
} else {
current = current.getNext();
return get(position, i+1, current);
}
}
public Node getHead() {
return head;
}
private int getInitPosition(){
return (int) (Math.random()*dimension);
}
public int getNumRows() {
return numRows;
}
public int getNumColumns() {
return numColumns;
}
public int getDimension() {
return dimension;
}
public int getNumSnakes() {
return numSnakes;
}
public int getNumLadders() {
return numLadders;
}
}
i get a nullPointerException on the method createSnakes, i dont get why this is happening so if someone has an idea of why it happens please tell me.
A NullPointerException is thrown when you are trying to call a method on an object reference, which has a value of null.
String str = null
str.substring(1) // This will throw NPE, because str == null
To solve this problem you need to understand which object is null and make sure it is properly initialised in the code before it is ever used.
In your case it probably has to do with random number generation aspect of the code ... you might not be generating enough objects/numbers and because of this some things are uninitialised.
To achieve this you can either use a debugger or print out values of variables you suspect might contain null (hint: use the line number from the exception message) or print them out using System.out.ln or a logging library.
Also, take a look at this
Write a method to find the position of a given element in a stack counting from the top of the stack. More precisely,
the method should return 0 if the element occurs on the top, 1 if there is another element on top of it, and so on. If
the element occurs several times, the topmost position should be returned. If the element doesn’t occur at all, -1
must be returned.
You are asked to write this method in two different ways; one way is to implement it internally inside the
ArrayStack class and the other way is to implement it externally in a separate class. Important: At the end
the stack should be returned to the original state (i.e. no elements should be removed and the order of the elements
should not change).
This is the externall class
public class Stack{
public static int searchstack(ArrayStack z, int n) {
ArrayStack temp = new ArrayStack(z.size());
int c = 0;
boolean flag = false;
while (!z.isEmpty()) {
if (z.top() == n) {
flag = true;
return c;
}
if (z.top() != n) {
temp.push(z.pop());
c++;
flag = false;
}
}
if (flag == false) {
c = -1;
}
while (!temp.isEmpty() && !z.isFull()) {
z.push(temp.pop());
}
return c;
}
public static void main(String[] args) {
ArrayStack z = new ArrayStack(4);
z.push(3); // first element
z.push(7);// 2nd
z.push(8);// 3rd
z.push(1);// 4th
z.printStack();
int n = 3;
System.out.println("Searching externally for" + " " + n + " " + searchstack(z, n));
System.out.println("Searching internally for" +" "+n+" "+ z.searchfor(n)+" "); //THE ERROR IS HERE
}
}
And this is the ArrayClass
public class ArrayStack {
private int[] theStack;
private int maxSize;
private int top;
public ArrayStack(int s) {
maxSize = s;
theStack = new int[maxSize];
top = -1;
}
public void push(int elem) {
top++;
theStack[top] = elem;
}
public int pop() {
int result = theStack[top];
top--;
return result;
}
public int top() {
return theStack[top];
}
public boolean isFull() {
return (top == (maxSize - 1));
}
public boolean isEmpty() {
return (top == -1);
}
public int size() {
return (top + 1);
}
//HERE IS THE METHOD I IMPLEMENTED INTERNALLY AND CALL IT AT THE STACK CLASS
public int searchfor(int n) {
for (int i = top; i >= 0; i--) {
if (theStack[top] == n) {
return i;
}
}
return -1;
}
public void printStack() {
if (top == -1)
System.out.println("Stack is empty!!\n");
else {
System.out.println(theStack[top] + " <- top");
for (int i = top - 1; i >= 0; i--)
System.out.println(theStack[i]);
System.out.println();
}
}
}
The error appearing at the Stack class is at the last line of calling the searchfor method implemented in the Arraystack class , error says that there is no method implemented in Arraystack with the name searchfor (); thiugh I did implement it .whatseems to be the problem ?
You have a bug in your searchStack() implementation. You are losing elements if you find the one you are looking for and it isn't the topmost one.
How to fix your searchStack() method:
keep popping z until you have an empty ArrayStack. While doing so, add the value to a queue.
create valIndex and assign it -1.
Then go through the queue and remove the items from it and adding them to z. While doing so, check for the last occurence of the desired value and save it in valIndex.
if valIndex equals -1 return it. Else, use following equation to convert it to correct index and return:
valIndex = (z.size - 1) - valIndex
I want to initialize an Item Array but can't figure it out.
Here is my code.
public class HashTable<Item> {
private int m; // hash table size
private Item[] T; // hash table
HashTable(int M)
{
m = M;
T = new Item[M];
for(int i=0;i<M;i++){
Item T[i] = null;
}
}
...
...
SOLUTION
T = (Item[])new Object[M];
I think what you need is something like:
for(int i=0;i<M;i++){
T[i] = new Item(); // call some constructor here
}
You have
Item T[i] = ...
in your loop, while it should be just
T[i] = ...
So try these hints.
Also do this:
T = (Item[])new Object[M];
as Kumar suggested in his reply.
The thing is that Item is not really a type here. You need
to read how generics are actually compiled into bytecode,
and you will see what happens under the hood.
You are trying to create the array of Generic type,Please look at this post.
How to create a generic array in Java?
Assuming you created the class item you could call it like this:
public class HashTable
{
private int tableSize; // hash table size
private Item[] table; // hash table
public static void main(String[] args)
{
// where 10 is the number of nodes
Item[] myTable = createHashTable(10);
}
private static Item[] createHashTable(int size)
{
Item[] table = new Item[size];
for(int i = 0; i < table.length; i++)
{
table[i] = new Item(i);
}
}
}
However if you want to see an example of a full HashTable implementation:
/*
* HashTable.java
*
*
*/
/**
* A class that implements a hash table that employs open addressing
* using either linear probing, quadratic probing, or double hashing.
*/
public class HashTable {
/* Private inner class for an entry in the hash table */
private class Entry {
private String key;
private LLList valueList; // all of the values with this key
private boolean hasBeenRemoved; // has this entry been removed?
private Entry(String key, int value) {
this.key = key;
valueList = new LLList();
valueList.addItem(value, 0);
hasBeenRemoved = false;
}
}
// parameters for the second hash function -- see h2() below
private static final int H2_MIN = 5;
private static final int H2_DIVISOR = 11;
// possible types of probing
public static final int LINEAR = 0;
public static final int QUADRATIC = 1;
public static final int DOUBLE_HASHING = 2;
public static final int NUM_PROBE_TYPES = 3;
private Entry[] table; // the hash table itself
private int probeType = LINEAR; // the type of probing
// keeps track of how many times we perform a probe of a given length
private int[] probeLengthCount;
public HashTable(int size, int probeType) {
if (probeType >= 0 && probeType < NUM_PROBE_TYPES)
this.probeType = probeType;
else
throw new IllegalArgumentException("invalid probeType: " +
probeType);
table = new Entry[size];
probeLengthCount = new int[size + 1];
for (int i = 0; i <= size; i++)
probeLengthCount[i] = 0;
}
public HashTable(int size) {
// Call the other constructor to do the work.
this(size, LINEAR);
}
/* first hash function */
private int h1(String key) {
int h1 = key.hashCode() % table.length;
if (h1 < 0)
h1 += table.length;
return h1;
}
/* second hash function */
private int h2(String key) {
int h2 = key.hashCode() % H2_DIVISOR;
if (h2 < 0)
h2 += H2_DIVISOR;
h2 += H2_MIN;
return h2;
}
/*
* probeIncrement - returns the amount by which the current index
* should be incremented to obtain the nth element in the probe
* sequence
*/
private int probeIncrement(int n, int h2) {
if (n <= 0)
return 0;
switch (probeType) {
case LINEAR:
return 1;
case QUADRATIC:
return (2*n - 1);
case DOUBLE_HASHING:
default:
return h2;
}
}
/*
* probe - attempt to find a slot in the hash table for the specified key.
*
* If key is currently in the table, it returns the index of the entry.
* If key isn't in the table, it returns the index of the first empty cell
* in the table.
* If overflow occurs, it returns -1.
*/
private int probe(String key) {
int i = h1(key); // first hash function
int h2 = h2(key); // second hash function
int positionsChecked = 1;
// keep probing until we get an empty position or a match
while (table[i] != null && !key.equals(table[i].key)) {
if (positionsChecked == table.length) {
probeLengthCount[positionsChecked]++;
return -1;
}
i = (i + probeIncrement(positionsChecked, h2)) % table.length;
positionsChecked++;
}
probeLengthCount[positionsChecked]++;
return i;
}
/**
* insert - insert the specified (key, value) pair in the hash table
*/
public void insert(String key, int value) {
if (key == null)
throw new IllegalArgumentException("key must be non-null");
int i = h1(key);
int h2 = h2(key);
int positionsChecked = 1;
int firstRemoved = -1;
while (table[i] != null && !key.equals(table[i].key)) {
if (table[i].hasBeenRemoved && firstRemoved == -1)
firstRemoved = i;
if (positionsChecked == table.length)
break;
i = (i + probeIncrement(positionsChecked, h2)) % table.length;
positionsChecked++;
}
probeLengthCount[positionsChecked]++;
if (table[i] != null && key.equals(table[i].key))
table[i].valueList.addItem(value, 0);
else if (firstRemoved != -1)
table[firstRemoved] = new Entry(key, value);
else if (table[i] == null)
table[i] = new Entry(key, value);
else
throw new RuntimeException("overflow occurred");
}
/**
* search - search for the specified key, and return the
* associated list of values, or null if the key is not in the
* table
*/
public LLList search(String key) {
if (key == null)
throw new IllegalArgumentException("key must be non-null");
int i = probe(key);
if (i == -1 || table[i] == null)
return null;
else
return table[i].valueList;
}
/**
* remove - remove from the table the entry for the specified key
*/
public void remove(String key) {
if (key == null)
throw new IllegalArgumentException("key must be non-null");
int i = probe(key);
if (i == -1 || table[i] == null)
return;
table[i].key = null;
table[i].valueList = null;
table[i].hasBeenRemoved = true;
}
/**
* printStats - print the statistics for the table -- i.e., the
* number of keys and items, and stats for the number of times
* that probes of different lengths were performed
*/
public void printStats() {
int numProbes = 0;
int probeLengthSum = 0;
int numKeys = 0;
for (int i = 0; i < table.length; i++) {
if (table[i] != null && !table[i].hasBeenRemoved)
numKeys++;
}
System.out.println("\n" + numKeys + " keys");
System.out.println("probe-length stats:");
System.out.println("length\tcount");
for (int i = 1; i <= table.length; i++) {
if (probeLengthCount[i] != 0)
System.out.println(i + "\t" + probeLengthCount[i]);
numProbes += probeLengthCount[i];
probeLengthSum += (probeLengthCount[i] * i);
}
System.out.println("average probe length = " +
(double)probeLengthSum / numProbes);
}
}
Here is the second file for a Linked-Linked-List
/*
* LLList.java
*
*
*/
import java.util.*;
/**
* A class that implements our simple List interface using a linked list.
* The linked list includes a dummy head node that allows us to avoid
* special cases for insertion and deletion at the front of the list.
*/
public class LLList implements List {
// Inner class for a node. We use an inner class so that the LLList
// methods can access the instance variables of the nodes.
private class Node {
private Object item;
private Node next;
private Node(Object i, Node n) {
item = i;
next = n;
}
}
private Node head; // dummy head node
private int length; // # of items in the list
/**
* Constructs a LLList object for a list that is initially empty.
*/
public LLList() {
head = new Node(null, null);
length = 0;
}
/*
* getNode - private helper method that returns a reference to the
* ith node in the linked list. It assumes that the value of the
* parameter is valid.
*
* If i == -1, it returns a reference to the dummy head node.
*/
private Node getNode(int i) {
Node trav = head;
int travIndex = -1;
while (travIndex < i) {
travIndex++;
trav = trav.next;
}
return trav;
}
/** getItem - returns the item at position i in the list */
public Object getItem(int i) {
if (i < 0 || i >= length)
throw new IndexOutOfBoundsException();
Node n = getNode(i);
return n.item;
}
/**
* addItem - adds the specified item at position i in the list,
* shifting the items that are currently in positions i, i+1, i+2,
* etc. to the right by one. Always returns true, because the list
* is never full.
*
* We don't need a special case for insertion at the front of the
* list (i == 0), because getNode(0 - 1) will return the dummy
* head node, and the rest of insertion can proceed as usual.
*/
public boolean addItem(Object item, int i) {
if (i < 0 || i > length)
throw new IndexOutOfBoundsException();
Node newNode = new Node(item, null);
Node prevNode = getNode(i - 1);
newNode.next = prevNode.next;
prevNode.next = newNode;
length++;
return true;
}
/**
* removeItem - removes the item at position i in the list,
* shifting the items that are currently in positions i+1, i+2,
* etc. to the left by one. Returns a reference to the removed
* object.
*
* Here again, we don't need a special case for i == 0 (see the
* note accompanying addItem above).
*/
public Object removeItem(int i) {
if (i < 0 || i >= length)
throw new IndexOutOfBoundsException();
Node prevNode = getNode(i - 1);
Object removed = prevNode.next.item;
prevNode.next = prevNode.next.next;
length--;
return removed;
}
/** length - returns the number of items in the list */
public int length() {
return length;
}
/**
* isFull - always returns false, because the linked list can
* grow indefinitely and thus the list is never full.
*/
public boolean isFull() {
return false;
}
/**
* toString - converts the list into a String of the form
* [ item0 item1 ... ]
*/
public String toString() {
String str = "[ ";
Node trav = head.next; // skip over the dummy head node
while (trav != null) {
str += (trav.item + " ");
trav = trav.next;
}
str += "]";
return str;
}
/**
* iterator - returns an iterator for this list
*/
public ListIterator iterator() {
return new LLListIterator();
}
/*
*** private inner class for an iterator over an LLList ***
*/
private class LLListIterator implements ListIterator {
private Node nextNode; // the next node to visit
private Node lastVisitedNode; // the most recently visited node
public LLListIterator() {
nextNode = head.next;
lastVisitedNode = null;
}
/**
* hasNext - does the iterator have additional items to visit?
*/
public boolean hasNext() {
return (nextNode != null);
}
/**
* next - returns a reference to the next Object in the iteration
*/
public Object next() {
if (nextNode == null)
throw new NoSuchElementException();
Object item = nextNode.item;
lastVisitedNode = nextNode;
nextNode = nextNode.next;
return item;
}
}
}
Now I'm not sure anybody can really help me with this, since it's a pretty sizable amount of code to go through, but any help would be greatly appreciated. Here is my relevant code:
public class BTree implements Iterable<String> {
/** Left child */
BTree left;
/** Right Child */
BTree right;
/** Comparator to use for sorting */
Comparator<String> comp;
/** Parent node */
BTree parent;
/** String stored in this leaf */
String s;
/** # of iterators currently working on it */
int active = 0;
/** Size of the BTree */
int size;
public void build(Iterable<String> iter, int numStrings) {
if (this.active > 0) {
throw new ConcurrentModificationException();
}
else {
Iterator<String> itr = iter.iterator();
while (numStrings != 0 && itr.hasNext()) {
String s = itr.next();
if (!this.contains(s)) {
this.insert(s);
this.size++;
numStrings--;
}
}
}
}
/**
* Inserts the string into the given BTree
* #param str - String to insert
*/
private void insert(String str) {
if (this.s.equals("")) {
this.s = str;
}
else if (this.comp.compare(str, this.s) > 0) {
if (this.right == null) {
BTree bt = BTree.binTree(this.comp);
bt.s = str;
this.right = bt;
bt.parent = this;
}
else {
this.right.insert(str);
}
}
else if (this.comp.compare(str, this.s) < 0) {
if (this.left == null) {
BTree bt = BTree.binTree(this.comp);
bt.s = str;
this.left = bt;
bt.parent = this;
}
else {
this.left.insert(str);
}
}
}
private class BTreeIterator implements Iterator<String> {
/** Current BTree being iterated over */
BTree current;
/** How many next() calls have there been */
int count;
/** Size of the BTree */
int max;
/** Constructor for BTreeIterator
* #param current
*/
BTreeIterator(BTree current) {
this.current = current;
this.count = 0;
this.max = current.size;
active++;
}
/** Returns true if there is another string to iterate over
* #return boolean
*/
public boolean hasNext() {
if (this.count != this.max) {
return true;
}
else {
active--;
return false;
}
}
/**
* Returns the next string in the iterator
* #return String
*/
public String next() {
if (this.count == 0) {
this.count++;
current = this.current.getLeftMost();
if (this.current.s.equals("")) {
throw new NoSuchElementException();
}
return this.current.s;
}
else if (this.current.right != null) {
this.current = this.current.right.getLeftMost();
this.count++;
return this.current.s;
}
else {
BTree tree = this.current;
while (tree.parent.right == tree) {
tree = tree.parent;
}
this.current = tree.parent;
this.count++;
return this.current.s;
}
}
/** Throws an exception since we aren't removing anything from the trees
*/
public void remove() {
throw new UnsupportedOperationException();
}
}
}
}
The Exception gets thrown at the while (tree.parent.right == tree) line in the next() method of the iterator. The funny thing is, my code has worked just fine with a comparator comparing lexicographically and reverse lexicographically sorting through a file of 24000 words. It only throws the exception when using the following comparator:
class StringWithOutPrefixByLex implements Comparator<String> {
/**
* compares o1 and o2
* #param o1 first String in comparison
* #param o2 second String in comparison
* #return a negative integer, zero, or a positive integer
* as the first argument is less than, equal to, or
* greater than the second.
*/
public int compare(String o1, String o2) {
String s1, s2;
if(o1.length() > 4){
s1 = o1.substring(3);
}
else {
s1 = o1;
}
if(o2.length() > 4){
s2 = o2.substring(3);
}
else {
s2 = o2;
}
return s1.compareTo(s2);
}
}
Even weirder, it works fine with that comparator for the same file up to 199 words, but as soon as I have it build up to 200 words it breaks.
EDIT: I have determined that the Exception is due to the code trying to reference tree.parent.right while tree.parent is null, but I can't figure out WHY it's trying to do that. As far as I can tell, my code should never try to call a null tree.parent, as explained by my comment below.
Well, you do not actually show enough of your code, but, what about the root node of your BTree? What is the value of BTree.parent in the root node? null?
If the root node has a null parent, then, in this while loop, it is likely that :
while (tree.parent.right == tree) {
tree = tree.parent;
}
... will get to the root node, the tree will be set to tree.parent, which is null, and then the while loop test will fail because tree.parent.right will attempt to dereference a null pointer.