inserting and removing from a max heap java - java

I have written my java implementation of a max heap made of nodes that contain two things, a string and a double value that can be accessed from each. They are supposed to be inserted by rank of their double value. I'm not sure if its my insert or remove that isn't working properly, but when I try to remove the top five max values from the heap I'm not getting what I'm supposed to be getting. Any ideas where the hiccup is? There are methods in these such as isfull and isempty to test the base cases of it being empty or full of course... Count is total number of nodes in the array (heap is the array).
public boolean insert(String W, double R){
HeapNode word = new HeapNode(W,R);
if (isFull()){
return false;
}
else {
count++;
heap[count - 1] = word;
siftUp(count - 1);
}
System.out.println("Added");
return true;
}
public boolean siftUp(int place){
int parentNode;
HeapNode tmp;
if (place != 0) {
//parent node of place
//parentNode = getParentNode(place);
parentNode = ((place-1) / 2);
if (heap[parentNode].getDouble() < heap[place].getDouble()) {
tmp = heap[parentNode];
heap[parentNode] = heap[place];
heap[place] = tmp;
siftUp(parentNode);
}
}
return true;
}
Thats the insert, now the remove:
public HeapNode remove(){
HeapNode maxValue;
if (isEmpty()){
return null;
}
else{
// Where does the max value always reside?
maxValue = heap[0];
// What value will take the root? Last one.
heap[0] = heap[count-1];
count--; ;
// Begin percolate down at index of root
int hole = 0;
int child;
HeapNode temp = heap[hole];
while( hole * 2 + 1 < count)
{
// Index of left child of node in hole index
child = 2 * hole + 1;
//find greater child
if(child != count && (heap[child + 1].getDouble()) > (heap[child].getDouble()))
child++; //swap index
if((heap[child].getDouble()) > (temp.getDouble())) //last comparison
heap[hole] = heap[child];
else
break;
hole = child;
}
heap[hole] = temp;
}
return maxValue;
}
Test case I'm using. Entering nodes in this order based on their double values:
1.0, 0.8, 0.9, 0.8, 1.0, 0.6, 1.0, 1.0, 0.8, 1.0, 0.7, 1.0, 0.8
Removing the first five I should be getting all 1.0's? I'm getting 1.0, 0.8, 1.0, 0.7, 1.0 as the five.

I can spot 2 mistakes.
You have parentNode = (place / 2);
in the siftup method. And apparently you're using 0-based array index so Node 0 is supposed to have 1 and 2 as children, but this equation gives 1 as the parent of 2.
Change it to parentNode = ((place-1) / 2);.
The other one is in the next line:
if (heap[parentNode].getDouble() > heap[place].getDouble()).
This will bubbles the min node to the top, not the max node.

Another problem you have is this statement in your remove method:
//find greater child
if(child != count && (heap[child + 1].getDouble()) > (heap[child].getDouble()))
child++; //swap index
Here, you already know that child < count, because you tested that in the loop. But if (child+1) == count, then you're testing the current element against the previous last element in the heap.
I think what you want is:
if ((child < count-1) && (heap[child + 1].getDouble()) > (heap[child].getDouble()))

Related

using 'extract' method to iteratively remove smallest element from min heap and copy to designated arrayList as a method of obtaining a sorted list

I have a program that reads in a text file and creates a number of nodes elements that can be used to build into a MIN heap.
What I'm struggling with is, after the Min heap has been correctly built, I'm supposed to sort the elements by using an 'extract' method to remove the smallest element at the root and adding it to a separate ArrayList intended to contain the elements in sorted order.
Of course we are supposed to extract one element at a time and add it to our new arraylist and then, remove that element from the heap of remaining nodes, so that the heap keeps decreasing by one element and the sorted arraylist keeps increasing by one element until there are no remaining elements in the heap.
I believe the problem is that after extracting the root element of the min heap, the root element itself isn't erased, it seems to remain in the heap even though my extract method is supposed to overwrite the removed root element by replacing it with the last item in the heap and then decrementing the heap size and re-applying the 'heapify' method to restore the heap property.
My code is fairly simple, the main method is long but the significant part is as follows:
g = new Graph();
readGraphInfo( g );
DelivB dB = new DelivB(inputFile, g);
int numElements = g.getNodeList().size();
ArrayList<Node> ordered_nodeList = new ArrayList<Node>(15);
ArrayList<Node> sorted_nodeList = new ArrayList<Node>(15);
h = new Heap(ordered_nodeList, g);
for (int i = 0; i < numElements; i++)
{
ordered_nodeList.add(i, g.getNodeList().get(i));
h.Build_min_Heap(ordered_nodeList);
System.out.println("Heap: \n");
System.out.println("\n**********************" + "\nProg 340 line 147" +h.heapClass_toString(ordered_nodeList));
//System.out.println("the " + i + "th item added at index " + i + " is: " + ordered_nodeList.get(i).getAbbrev());
}
for (int j = 0; j < numElements; j++)
{
sorted_nodeList.add(j, h.heap_Extract(ordered_nodeList));
System.out.println("the "+j+"th item added to SORTED node list is: "+sorted_nodeList.get(j).getAbbrev()+ " "+ sorted_nodeList.get(j).getVal());
//h.heap_Sort(ordered_nodeList);
System.out.println("\nthe 0th remaining element in ordered node list is: " + ordered_nodeList.get(0).getVal());
h.Build_min_Heap(ordered_nodeList);
}
for (Node n : sorted_nodeList)
{
System.out.println("sorted node list after extract method*****************\n");
System.out.println(n.toString());
}
The output I keep getting is as follows:
the 0th remaining element in ordered node list is: 55
the 1th item added to SORTED node list is: F 55
the 0th remaining element in ordered node list is: 55
the 2th item added to SORTED node list is: F 55
the 0th remaining element in ordered node list is: 55
the 3th item added to SORTED node list is: F 55
the 0th remaining element in ordered node list is: 55
the 4th item added to SORTED node list is: F 55
the 0th remaining element in ordered node list is: 55
the 5th item added to SORTED node list is: F 55
the 0th remaining element in ordered node list is: 55
sorted node list after extract method*****************
F
sorted node list after extract method*****************
F
sorted node list after extract method*****************
F
sorted node list after extract method*****************
F
sorted node list after extract method*****************
F
sorted node list after extract method*****************
F
My Heap class is as follows:
import java.util.*;
public class Heap
{
int heapSize;
ArrayList unordered_nodeList;
ArrayList ordered_nodeList;
Graph gr;
nodes
public Heap(ArrayList<Node> A, Graph g)
{
unordered_nodeList = g.getNodeList();
heapSize = unordered_nodeList.size();
ordered_nodeList = A;
gr = g;
}
public ArrayList getUnordered_nodeList() {
return unordered_nodeList;
}
public void setUnordered_nodeList(ArrayList unordered_nodeList) {
this.unordered_nodeList = unordered_nodeList;
}
public ArrayList getOrdered_nodeList() {
return ordered_nodeList;
}
public void setOrdered_nodeList(ArrayList ordered_nodeList) {
this.ordered_nodeList = ordered_nodeList;
}
public int getHeapSize() {
return heapSize;
}
public void setHeapSize(int heapSize) {
this.heapSize = heapSize;
}
//heap methods
public int Parent(ArrayList<Node> A, int i)
{
//if (i == 1)
//return (Integer)null;
if (i%2 != 0)
return i/2;
else
return (i-1)/2;
}
public int Left(ArrayList<Node> A, int i)
{
if (2*i < A.size()-1)
return (2*i)+1;
else
return i;
//return (Integer)null;
}
public int Right(ArrayList<Node> A, int i)
{
if ((2*i)+1 < A.size()-1)
return 2*i+2;
else
return i;
//return (Integer)null;
}
public void Heapify(ArrayList<Node> A, int i)
{
Node smallest;
Node temp;
int index;
int l = Left(A,i);
int r = Right(A,i);
if (l <= heapSize-1 && Integer.parseInt(A.get(l).getVal()) < Integer.parseInt(A.get(i).getVal()))
{
//left child is smaller
smallest = A.get(l);
index = l;
}
else
{
//parent node is smaller
smallest = A.get(i);
index = i;
}
if (r <= heapSize-2 && Integer.parseInt(A.get(r).getVal()) < Integer.parseInt(smallest.getVal()))
{
//right child is smaller
smallest = A.get(r);
index = r;
}
if (index != i)
{
//if the smallest element is not the parent node
//swap the smallest child with the parent
temp = A.get(i);
A.set(i, A.get(index));
A.set(index, temp);
//recursively call heapify method to check next parent/child relationship
Heapify(A, index);
//System.out.println(this.heapClass_toString(ordered_nodeList));
}
//System.out.println("\n**********************" + "\nHeapify line 123" + this.heapClass_toString(ordered_nodeList));
}
//method to construct min heap from unordered arraylist of nodes
public void Build_min_Heap(ArrayList<Node> A)
{
int i;
int heapSize = A.size();
for (i = (heapSize/2); i>=0; i--)
{
//System.out.println(gr.toString2() +"\n");
//System.out.println("build heap ********** line 138" +this.heapClass_toString(ordered_nodeList));
Heapify(A, i);
//System.out.print(gr.toString2()+"\n");
}
}
//method to sort in descending order, a min heap
public void heap_Sort(ArrayList<Node> A)
{
Node temp;
//Build_min_Heap(A);
while (A.size() > 0)
{
///System.out.println("\n******************************\n heap_sort line 180" +this.heapClass_toString(ordered_nodeList));
//for (int i = 0; i <= A.size()-1; i++)
for(int i = A.size()-1; i >= 1; i--)
{
//exchange a[0] with a[i]
temp = A.get(0);
A.set(0, A.get(i));
A.set(i, temp);
//System.out.println(this.heapClass_toString(ordered_nodeList));
//decrement heapSize
heapSize--;
//recursive heapify call
Heapify(A, 0);
System.out.println("\n******************************\n heap_sort line 203" +this.heapClass_toString(ordered_nodeList));
}
System.out.println("\n******************************\n heap_sort line 206" +this.heapClass_toString(ordered_nodeList));
Heapify(A, A.size()-1);
}
}
public Node heap_Extract(ArrayList<Node> A)
{
//Node min = null;
//if (heapSize>0)
//while (A.get(0) != null && heapSize > 0)
Node min = A.get(0);
//min = A.get(0);
while (heapSize>0)
{
min = A.get(0);
A.set(0, A.get(heapSize-1));
//decrement heapSize
heapSize--;
Heapify(A, 0);
}
return min;
}
//return min;
public String heapClass_toString(ArrayList A)
{
String s = "Graph g.\n";
if (A.size() > 0 )
{
for (int k = 0; k < A.size(); k++ )
{
//output string to print each node's mnemonic
String t = this.getOrdered_nodeList().get(k).toString();
s = s.concat(t);
}
}
return s;
}
}
One issue is the following loop in your heap_Extract() method:
while (heapSize>0)
{
min = A.get(0);
A.set(0, A.get(heapSize-1));
//decrement heapSize
heapSize--;
Heapify(A, 0);
}
This loop will run over and over again until your heap has nothing in it, and then the function will return the last node min was set to (which should be the largest element in the original heap, if Heapify is implemented correctly). Subsequent calls will see that heapSize == 0, skip the loop entirely, and immediately and return min, which will be set to A.get(0), which will still be the largest element in the original Heap. You should ensure that the code in the body of this loop only runs at most one time (i.e. it shouldn't be in a loop, but perhaps should be guarded by some other conditional branch statement) for each call of heap_Extract().

Heapify with ArrayList

I wrote this method to test my priority queue, which has as parameter an ArrayList and a Comparator:
#Test
public void testPriorityQueue_ExtractMax() {
PriorityQueue queue = new PriorityQueue(new IntegerComparator());
Integer[] arrayExp={14, 9};
queue.insert(16);
queue.insert(9);
queue.insert(14);
queue.extractMax();
assertArrayEquals(arrayExp, queue.getArray().toArray());
}
Now, if I execute it, it says that the first elements in my result is 9, but I has to be 14 (the new root of my queue). These are the methods extract max and heapify. How can I solve it?
public void heapify(int index) {
int largest = index;
int leftIndex = 2 * index + 1;
int rightIndex = 2 * index + 2;
if (leftIndex < queue.size() && c.compare(queue.get(index), (queue.get(leftIndex))) < 0)
largest = leftIndex;
if (rightIndex < queue.size() && c.compare(queue.get(largest), queue.get(rightIndex)) < 0)
largest = rightIndex;
if (largest != index) {
swap(index, largest);
heapify(largest);
}
}
public T extractMax() {
if (queue.size() == 0) return null;
T min = queue.get(0);
queue.remove(0);
queue.set(0, queue.get(queue.size() - 1));
heapify(0);
return min;
}
This is the IntegerComparator:
public class IntegerComparator implements Comparator<Integer>{
#Override
public int compare(Integer l1, Integer l2) {
int result = l1.compareTo(l2);
if(result != 0)
return result;
return -1;
}
}
EDIT_2: This is my insert method, can it be the problem:
public void insert(T elem) {
int i = queue.size();
int parentIndex = (i - 1) / 2;
while (i > 0 && c.compare(elem, queue.get(parentIndex)) == 1) {
queue.set(i, queue.get(parentIndex));
i = parentIndex;
parentIndex = (i - 1) / 2;
}
queue.add(i, elem);
}
As a suggestion, consider adding an unused element at index 0 so that accessing the parents/children of each node is more intuitive.
Example:
Consider the heap heap = [-1, 6, 4, 5, 2, 1, 4, 3] where the root is defined as heap[1], and the data for the heap is located from index = 1 to the heap's size.
To access the children of a node at index, it is intuitive to say that the left child is defined as heap[2 * index] and the right child is defined as heap[2 * index + 1]. Similarly, to access the parent node of a node at index, one can use int truncation to access parents:
int parentInd = (int)(index/2);
T parent = heap[parentInd];
Solution:
As raul1ro has pointed out, you are losing the data from index 0 that you were not intending to remove.
In extractMax():
T min = queue.get(0);
queue.remove(0);
queue.set(0, queue.get(queue.size() - 1));
should be:
T min = queue.get(0); //Get min
T temp = queue.get(queue.size() - 1); //Get the last element in heap as temp
queue.remove(queue.size - 1); //Remove the last element
queue.set(0, temp); //Set the root to the temp value so that you can heapify
This will make it so that you only lose 1 element when you extractMax()
Hope that helps!
When you do this queue.remove(i); automatically shift all elements, after index i, to left with one position.
https://www.tutorialspoint.com/java/util/arraylist_remove.htm
And with queue.set(0, queue.get(queue.size() - 1)); You just set value of last index from queue on index 0 and lose value from index 0, but it still remain on last position.
After reading insert method
At queue.set(i, queue.get(parentIndex)); if i = queue.size() in first step, that mean index i don't exist in queue.

Average of each level in a Binary Tree

I am trying to find the average of each level in a binary tree. I am doing BFS. I am trying to do it using a null node. Whenever I find a dummy node, that means I am at the last node at that level. The problem I am facing is that I am not able to add average of the last level in a tree using this. Can Someone Help me?
Consider example [3,9,20,15,7]
I am getting the output as [3.00000,14.50000]. Not getting the average of the last level that is 15 and 7
Here's my code
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> list = new ArrayList<Double>();
double sum = 0.0;
Queue<TreeNode> q = new LinkedList<TreeNode>();
TreeNode temp = new TreeNode(0);
q.offer(root);
q.offer(temp);
int count = 0;
while(!q.isEmpty()){
root = q.poll();
sum += root.val;
if(root != temp)
{
count++;
if(root.left != null){
q.offer(root.left);
}
if(root.right != null){
q.offer(root.right);
}
}
else
{
if(!q.isEmpty()){
list.add(sum / count);
sum = 0;
count = 0;
q.add(temp);
}
}
}
return list;
}
}
Take a look at this code, which executes whenever you find the marker for the end of the current level:
if(!q.isEmpty()){
list.add(sum / count);
sum = 0;
count = 0;
q.add(temp);
}
This if statement seems to be designed to check whether you've finished the last row in the tree, which you could detect by noting that there are no more entries in the queue that would correspond to the next level. In that case, you're correct that you don't want to add the dummy node back into the queue (that would cause an infinite loop), but notice that you're also not computing the average in the row you just finished.
To fix this, you'll want to compute the average of the last row independently of reseeding the queue, like this:
if(!q.isEmpty()){
q.add(temp);
}
list.add(sum / count);
sum = 0;
count = 0;
There's a new edge case to watch out for, and that's what happens if the tree is totally empty. I'll let you figure out how to proceed from here. Good luck!
I would use recursive deep scan of the tree. On each node I would push the value into a map with a pair .
I DID NOT test that code but it should be along the lines.
void scan(int level, TreeNode n, Map<Integer, List<Integer> m) {
List l = m.get(level); if (l==null) {
l = new ArrayList();
m.put(level, l);
}
l.add(n.val);
int nextLevel = level + 1;
if (n.left != null) scan(nextLevel, n.left, m);
if (n.right != null) scan(nextLevel, n.right, m);
}
Once the scan is done I can calculate the average for each level.
for (int lvl in m.keyset()) {
List l = m.get(lvl);
// MathUtils.avg() - it is obvious what it should be
double avg = MathUtils.avg(l);
// you code here
}

Reduced time complexity of inner loop: Find count of elements greater than current element in the first loop and store that in solved array

I want to reduce the complexity of this program and find count of elements greater than current/picked element in first loop (array[])and store the count in solved array(solved[]) and loop through the end of the array[]. I have approached the problem using a general array based approach which turned out to have greater time complexity when 2nd loop is huge.
But If someone can suggest a better collection here in java that can reduce the complexity of this code that would also be highly appreciated.
for (int i = 0; i < input; i++) {
if (i < input - 1) {
count=0;
for (int j = i+1; j < input; j++) {
System.out.print((array[i])+" ");
System.out.print("> ");
System.out.print((array[j]) +""+(array[i] > array[j])+" ");
if (array[i] > array[j]) {
count++;
}
}
solved[i] = count;
}
}
for (int i = 0; i < input; i++) {
System.out.print(solved[i] + " ");
}
What I want to achieve in simpler terms
Input
Say I have 4 elements in my
array[] -->86,77,15,93
output
solved[]-->2 1 0 0
2 because after 86 there are only two elements 77,15 lesser than 86
1 because after 77 there is only 15 lesser than 77
rest 15 <93 hence 0,0
So making the code simpler and making the code faster aren't necessarily the same thing. If you want the code to be simple and readable, you could try a sort. That is, you could try something like
int[] solved = new int[array.length];
for (int i = 0; i < array.length; i++){
int[] afterward = Arrays.copyOfRange(array, i, array.length);
Arrays.sort(afterward);
solved[i] = Arrays.binarySearch(afterward, array[i]);
}
What this does it it takes a copy of the all the elements after the current index (and also including it), and then sorts that copy. Any element less than the desired element will be beforehand, and any element greater will be afterward. By finding the index of the element, you're finding the number of indices before it.
A disclaimer: There's no guarantee that this will work if duplicates are present. You have to manually check to see if there are any duplicate values, or otherwise somehow be sure you won't have any.
Edit: This algorithm runs in O(n2 log n) time, where n is the size of the original list. The sort takes O(n log n), and you do it n times. The binary search is much faster than the sort (O(log n)) so it gets absorbed into the O(n log n) from the sort. It's not perfectly optimized, but the code itself is very simple, which was the goal here.
With Java 8 streams you could reimplement it like this:
int[] array = new int[] { 86,77,15,93 };
int[] solved =
IntStream.range(0, array.length)
.mapToLong((i) -> Arrays.stream(array, i + 1, array.length)
.filter((x) -> x < array[i])
.count())
.mapToInt((l) -> (int) l)
.toArray();
There is actually a O(n*logn) solution, but you should use a self balancing binary search tree such as red-black tree.
Main idea of the algorithm:
You will iterate through your array from right to left and insert in the tree triples (value, sizeOfSubtree, countOfSmaller). Variable sizeOfSubtree will indicate the size of the subtree rooted at that element, while countOfSmaller counts the number of elements that are smaller than this element and appear at the right side of it in the original array.
Why binary search tree? An important property of BST is that all nodes in the left subtree are smaller than the current node, and all in the right subtree are greater.
Why self-balancing tree? Because this will guarantee you O(logn) time complexity while inserting a new element, so for n elements in array that will give O(n*logn) in total.
When you insert a new element you will also calculate the value of countOfSmaller by counting elements that are currently in the tree and are smaller than this element - exactly what are we looking for. Upon inserting in the tree compare the new element with the existing nodes, starting with the root. Important: if the value of the new element is greater than the value of the root, it means that is also greater than all the nodes in the left subtree of root. Therefore, set countOfSmaller to the sizeOfSubtree of root's left child + 1 (because the new element is also greater than root) and proceed recursively in the right subtree. If it is smaller than root, it goes to the left subtree of root. In both cases increment sizeOfSubtree of root and proceed recursively. While rebalancing the tree, just update the sizeOfSubtree for nodes that are included in left/right rotation and that's it.
Sample code:
public class Test
{
static class Node {
public int value, countOfSmaller, sizeOfSubtree;
public Node left, right;
public Node(int val, int count) {
value = val;
countOfSmaller = count;
sizeOfSubtree = 1; /** You always add a new node as a leaf */
System.out.println("For element " + val + " the number of smaller elements to the right is " + count);
}
}
static Node insert(Node node, int value, int countOfSmaller)
{
if (node == null)
return new Node(value, countOfSmaller);
if (value > node.value)
node.right = insert(node.right, value, countOfSmaller + size(node.left) + 1);
else
node.left = insert(node.left, value, countOfSmaller);
node.sizeOfSubtree = size(node.left) + size(node.right) + 1;
/** Here goes the rebalancing part. In case that you plan to use AVL, you will need an additional variable that will keep the height of the subtree.
In case of red-black tree, you will need an additional variable that will indicate whether the node is red or black */
return node;
}
static int size(Node n)
{
return n == null ? 0 : n.sizeOfSubtree;
}
public static void main(String[] args)
{
int[] array = {13, 8, 4, 7, 1, 11};
Node root = insert(null, array[array.length - 1], 0);
for(int i = array.length - 2; i >= 0; i--)
insert(root, array[i], 0); /** When you introduce rebalancing, this should be root = insert(root, array[i], 0); */
}
}
As Miljen Mikic pointed out, the correct approach is using RB/AVL tree. Here is the code that can read and N testcase do the job as quickly as possible. Accepting Miljen code as the best approach to the given problem statement.
class QuickReader {
static BufferedReader quickreader;
static StringTokenizer quicktoken;
/** call this method to initialize reader for InputStream */
static void init(InputStream input) {
quickreader = new BufferedReader(new InputStreamReader(input));
quicktoken = new StringTokenizer("");
}
static String next() throws IOException {
while (!quicktoken.hasMoreTokens()) {
quicktoken = new StringTokenizer(quickreader.readLine());
}
return quicktoken.nextToken();
}
static int nextInt() throws IOException {
return Integer.parseInt(next());
}
static long nextLong() throws IOException {
return Long.parseLong(next());
}
static double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
public class ExecuteClass{
static int countInstance = 0;
static int solved[];
static int size;
static class Node {
public int value, countOfSmaller, sizeOfSubtree;
public Node left, right;
public Node(int val, int count, int len, int... arraytoBeused) {
countInstance++;
value = val;
size = len;
countOfSmaller = count;
sizeOfSubtree = 1; /** You always add a new node as a leaf */
solved = arraytoBeused;
solved[size - countInstance] = count;
}
}
static Node insert(Node node, int value, int countOfSmaller, int len, int solved[]) {
if (node == null)
return new Node(value, countOfSmaller, len, solved);
if (value > node.value)
node.right = insert(node.right, value, countOfSmaller + size(node.left) + 1, len, solved);
else
node.left = insert(node.left, value, countOfSmaller, len, solved);
node.sizeOfSubtree = size(node.left) + size(node.right) + 1;
return node;
}
static int size(Node n) {
return n == null ? 0 : n.sizeOfSubtree;
}
public static void main(String[] args) throws IOException {
QuickReader.init(System.in);
int testCase = QuickReader.nextInt();
for (int i = 1; i <= testCase; i++) {
int input = QuickReader.nextInt();
int array[] = new int[input];
int solved[] = new int[input];
for (int j = 0; j < input; j++) {
array[j] = QuickReader.nextInt();
}
Node root = insert(null, array[array.length - 1], 0, array.length, solved);
for (int ii = array.length - 2; ii >= 0; ii--)
insert(root, array[ii], 0, array.length, solved);
for (int jj = 0; jj < solved.length; jj++) {
System.out.print(solved[jj] + " ");
}
System.out.println();
countInstance = 0;
solved = null;
size = 0;
root = null;
}
}
}

Re-Sizing Hash Table

I'm attempting to resize my hash table however; I am keep getting a NullPointerException.
I know if the size is greater than 0.75 then the table size has to double, if it's less than 0.50 then the table size is halved. So far I have this..
public boolean add(Object x)
{
int h = x.hashCode();
if (h < 0) { h = -h; }
h = h % buckets.length;
Node current = buckets[h];
while (current != null)
{
if (current.data.equals(x)) { return false; }
// Already in the set
current = current.next;
}
Node newNode = new Node();
newNode.data = x;
newNode.next = buckets[h];
buckets[h] = newNode;
currentSize++;
double factor1 = currentSize * load1; //load1 = 0.75
double factor2 = currentSize * load2; //load2 = 0.50
if (currentSize > factor1) { resize(buckets.length*2); }
if (currentSize < factor2) { resize(buckets.length/2); }
return true;
}
Example. Size = 3. Max Size = 5
if we take the Max Size and multiply by 0.75 we get 3.75.
this is the factor that says if we pass it the Max Size must double
so if we add an extra element into the table the size is 4 and is > 3.75 thus the new Max Size is 10.
However; once we increase the size, the hashcode will change with the addition of a new element, so we call resize(int newSize)
private void resize(int newLength)
{
//
HashSet newTable = new HashSet(newLength);
for (int i = 0; i < buckets.length; i++) {
newTable.add(buckets[i]);
}
}
Here is my constructor if the buckets[i] confuses anyone.
public HashSet(int bucketsLength)
{
buckets = new Node[bucketsLength];
currentSize = 0;
}
I feel that the logic is correct, unless my resize method is not retrieving the elements.
If that is all your code for resize(), then you are failing to assign newTable to a class attribute, i.e. your old table. Right now you fill it with data and then don't do anything with it, since it is defined inside resize and therefore not available outside of it.
So you end up thinking you have a larger table now, but in fact you are still using the old one ;-)

Categories

Resources