Need Help Counting number of swaps in a MaxHeap - java

I'm currently working on a project where I have to create a max heap. I'm currently using my textbooks version of the heap which somewhat looks like:
public MaxHeap(int initialCapacity) {
if (initialCapacity < DEFAULT_CAPACITY)
initialCapacity = DEFAULT_CAPACITY;
else
checkCapacity(initialCapacity);
#SuppressWarnings("unchecked")
T[] tempHeap = (T[]) new Comparable[initialCapacity + 1];
heap = tempHeap;
lastIndex = 0;
initialized = true;
}
public T getMax() {
checkInitialization();
T root = null;
if (!isEmpty())
root = heap[1];
return root;
}
public boolean isEmpty() {
return lastIndex < 1;
}
public int getSize() {
return lastIndex;
}
public void clear() {
checkInitialization();
while (lastIndex > -1) {
heap[lastIndex] = null;
lastIndex--;
}
lastIndex = 0;
}
public void add(T newEntry) {
checkInitialization();
int newIndex = lastIndex + 1;
int parentIndex = newIndex / 2;
while ((parentIndex > 0) && newEntry.compareTo(heap[parentIndex]) > 0) {
heap[newIndex] = heap[parentIndex];
newIndex = parentIndex;
parentIndex = newIndex / 2;
}
heap[newIndex] = newEntry;
lastIndex++;
ensureCapacity();
}
public int getSwaps()
{
return swaps;
}
public T removeMax() {
checkInitialization();
T root = null;
if (!isEmpty()) {
root = heap[1];
heap[1] = heap[lastIndex];
lastIndex--;
reheap(1);
}
return root;
}
private void reheap(int rootIndex) {
boolean done = false;
T orphan = heap[rootIndex];
int leftChildIndex = 2 * rootIndex;
while (!done && (leftChildIndex <= lastIndex)) {
int largerChildIndex = leftChildIndex;
int rightChildIndex = leftChildIndex + 1;
if ((rightChildIndex <= lastIndex) && heap[rightChildIndex].compareTo(heap[largerChildIndex]) > 0) {
largerChildIndex = rightChildIndex;
}
if (orphan.compareTo(heap[largerChildIndex]) < 0) {
heap[rootIndex] = heap[largerChildIndex];
rootIndex = largerChildIndex;
leftChildIndex = 2 * rootIndex;
} else
done = true;
}
heap[rootIndex] = orphan;
}
Am I supposed to count the swaps in multiple places and print the total amount and if so where would i count them? I had previously tried to just enumerate swaps++ in the add method but i don't think that is the proper way of doing it.

You have to count the swap in both the add(T newEntry) method and reHeap method which is called from removeMax mathod.
In reHeap you start from the top and as you call it from removeMax where after removing the max(in Max Heap case) you replace the root with the last element and then you need to balance the heap. So the heap recursively goes down till the last level to balance which may require swap.
EDIT:
Add the swap inside following code block of reHeap:
if (orphan.compareTo(heap[largerChildIndex]) < 0) {
heap[rootIndex] = heap[largerChildIndex];
rootIndex = largerChildIndex;
leftChildIndex = 2 * rootIndex;
// increment the swap here as inside this block of reHeap only swap takes place.
swap++
}

Would these be the correct way of implementing it?
So the add method would be:
public void add(T newEntry) {
checkInitialization();
int newIndex = lastIndex + 1;
int parentIndex = newIndex / 2;
while ((parentIndex > 0) && newEntry.compareTo(heap[parentIndex]) > 0) {
heap[newIndex] = heap[parentIndex];
newIndex = parentIndex;
parentIndex = newIndex / 2;
swap++;
}
heap[newIndex] = newEntry;
lastIndex++;
ensureCapacity();
}
and the reheap would be:
private void reheap(int rootIndex) {
boolean done = false;
T orphan = heap[rootIndex];
int leftChildIndex = 2 * rootIndex;
while (!done && (leftChildIndex <= lastIndex)) {
int largerChildIndex = leftChildIndex;
int rightChildIndex = leftChildIndex + 1;
if ((rightChildIndex <= lastIndex) && heap[rightChildIndex].compareTo(heap[largerChildIndex]) > 0) {
largerChildIndex = rightChildIndex;
}
if (orphan.compareTo(heap[largerChildIndex]) < 0) {
heap[rootIndex] = heap[largerChildIndex];
rootIndex = largerChildIndex;
leftChildIndex = 2 * rootIndex;
swap++;
} else
done = true;
}
heap[rootIndex] = orphan;
}

Related

How do I stop this loop from changing the value?

I'm trying to implement a heapsort on an array of objects which has already been created. It is meant to be sorted according to their eventTime attribute, yet each eventTime attribute is set to the same as the others by the time the queue is sorted. Is there any way to fix this so that it creates a 'priorityqueue' in ascending order?
Main:
public static void main(String[] args) {
CustomerQueue cQ = new CustomerQueue(0, 0, false);
for (int i = 0; i < 10; i++) {
CustomerQueue cQ1 = new CustomerQueue(0, 0, false);
cQ.enqueue(cQ1);
System.out.println(cQ1.arrivalTime);
}
System.out.print("\n");
PriorityQueue pQ = new PriorityQueue(0, 0, 0, false);
while (!cQ.isEmpty()) {
for (CustomerQueue c : cQ.array) {
PriorityQueue pQ1 = new PriorityQueue(0, 0, 0, false);
pQ1.eventTime = c.arrivalTime;
pQ.enqueue(pQ1);
System.out.println(pQ1.eventTime);
cQ.dequeue();
}
}
pQ.sort(pQ.array);
System.out.println(Arrays.toString(pQ.array));
}
PriorityQueue:
class PriorityQueue {
PriorityQueue array[] = new PriorityQueue[10];
private int front;
private int rear;
private int count;
private int eventType;
double eventTime;
private double tallyTime;
private boolean paymentMethod;
public PriorityQueue(int evT, int eT, double tT, boolean pM) {
this.eventType = evT;
this.eventTime = eT;
this.tallyTime = tT;
this.paymentMethod = pM;
front = 0;
rear = -1;
count = 0;
}
public void enqueue(PriorityQueue pQ) {
if (isFull()) {
System.out.println("OverFlow\nProgram Terminated");
System.exit(1);
}
rear = (rear + 1);
array[rear] = pQ;
count++;
}
public void sort(PriorityQueue arr[]) {
int n = arr.length;
// Build heap (rearrange array)
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
// One by one extract an element from heap
for (int i = n - 1; i >= 0; i--) {
// Move current root to end
int temp = (int) arr[0].eventTime;
arr[0] = arr[i];
arr[i].eventTime = temp;
// call max heapify on the reduced heap
heapify(arr, i, 0);
}
}
void heapify(PriorityQueue arr[], int n, int i) {
int largest = i; // Initialize largest as root
int l = 2 * i + 1; // left = 2*i + 1
int r = 2 * i + 2; // right = 2*i + 2
// If left child is larger than root
if (l < n && arr[l].eventTime > arr[largest].eventTime) {
largest = l;
}
// If right child is larger than largest so far
if (r < n && arr[r].eventTime > arr[largest].eventTime) {
largest = r;
}
// If largest is not root
if (largest != i) {
int swap = (int) arr[i].eventTime;
arr[i] = arr[largest];
arr[largest].eventTime = swap;
// Recursively heapify the affected sub-tree
heapify(arr, n, largest);
}
}
public void dequeue() {
if (isEmpty()) {
System.out.println("UnderFlow\nProgram Terminated");
System.exit(1);
}
front = (front + 1) % array.length;
count--;
}
public boolean isEmpty() {
return (size() == 0);
}
public int size() {
return count;
}
public boolean isFull() {
return (size() == array.length);
}
public PriorityQueue peek() {
if (isEmpty()) {
System.out.println("UnderFlow\nProgram Terminated");
System.exit(1);
}
return array[front];
}
#Override
public String toString() {
return eventType + " " + eventTime + " " + tallyTime + " " + paymentMethod;
}
}
I see two parts which are most likely wrong and the cause of your issue:
In the heapify method you have:
int swap = (int) arr[i].eventTime;
arr[i] = arr[largest];
arr[largest].eventTime = swap;
And in the sort method you have:
int temp = (int) arr[0].eventTime;
arr[0] = arr[i];
arr[i].eventTime = temp;
Assuming you want to switch the CustomerQueue objects around inside the array, they should be this instead:
// In the heapify:
CustomerQueue swap = arr[i];
arr[i] = arr[largest];
arr[largest] = swap;
// In the sort:
CustomerQueue temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
What your code currently does in pseudo-code is this:
CustomerQueue ith has for example name = "I", eventTime = 1
CustomerQueue largest has for example name = "largest", eventTime = 2
int temp = (int) arr[i].eventTime; // temp is now 1
arr[i] = arr[largest]; // Both arr[i] AND arr[largest] are now CustomerQueue largest (with name = "largest" and eventTime = 2)
arr[i].eventTime = temp; // Both arr[i] AND arr[largest] are now changed to eventTime temp (which is 1)
So now both arr[i] and arr[largest] will hold: name = "largest" and eventTime = 1, as well as referencing the same CustomerQueue-instance.

find the shortest path in a number maze, Java

In a number maze, a player always starts from the square at the upper left and makes a certain number of moves which will take him/her to the square marked Goal if a solution exist. The value in each cell in the maze indicates how far a player must move horizontally or vertically from its current position.
My task is to find out if the shortest path to the cell labeled “Goal” and print it.
Input
the maze is in the form of square 2D array. The goal square is indicated by the number -1 in the maze description.
Output
For the maze, output the solution of the maze or the phrase “No Solution Possible.” Solutions should be output as a list of square coordinates in the format “(Row, Column)”, in the order in which they are visited from the start to the goal, including the starting cell. You will need to report the shortest solution from start to the goal. The shortest solution will be unique.
I have tried some solution, but I think there is problem that is the solution is always the first path I found not the shortest..
public class findShoretstPath
{
private static Stack<Node> stack = new Stack<>();
private static class Node
{
private int[] coordinate = new int[2];
private int data;
private Node Right, Left, Top, Bottom;
public Node(){}
}
public static boolean isValid(int[][] a, int x, int y)
{
if(x >= 0 && x < a.length && y >= 0 && y < a.length)
return true;
return false;
}
public static Node[][] nodeArray(int[][] a)
{
Node[][] nodeA = new Node[a.length][a.length];
for(int i = 0; i<nodeA.length; i++)
for(int j = 0; j<nodeA[i].length; j++)
{
nodeA[i][j] = new Node();
nodeA[i][j].coordinate[0] = i;
nodeA[i][j].coordinate[1] = j;
nodeA[i][j].data = a[i][j];
}
for(int i = 0; i<nodeA.length; i++)
for(int j = 0; j<nodeA[i].length; j++)
{
if(isValid(a, i, j+nodeA[i][j].data))
nodeA[i][j].Right = nodeA[i][j+nodeA[i][j].data];
if(isValid(a, i, j-nodeA[i][j].data))
nodeA[i][j].Left = nodeA[i][j-nodeA[i][j].data];
if(isValid(a, i+nodeA[i][j].data, j))
nodeA[i][j].Bottom = nodeA[i+nodeA[i][j].data][j];
if(isValid(a, i-nodeA[i][j].data, j))
nodeA[i][j].Top = nodeA[i-nodeA[i][j].data][j];
}
return nodeA;
}
public static boolean findPath(Node[][] s, int[][] t, int x, int y)
{
boolean b = false;
if(t[x][y] == 0)
{
t[x][y] = 1;
if(s[x][y].data == -1) b = true;
else
{
if(s[x][y].Right != null) b = findPath(s, t, x, y+s[x][y].data);
if(!b && s[x][y].Bottom != null) b = findPath(s, t, x+s[x][y].data, y);
if(!b && s[x][y].Left != null) b = findPath(s, t, x, y-s[x][y].data);
if(!b && s[x][y].Top != null) b = findPath(s, t, x-s[x][y].data, y);
}
if(b) stack.add(s[x][y]);
}
return b;
}
public static void main(String[] args)
{
int[][] maze = {{1,1,1,1,1},
{1,1,1,1,1},
{1,1,1,1,1},
{1,1,1,1,3},
{4,1,1,3,-1}};
Node[][] net = nodeArray(maze);
int[][] path = new int[maze.length][maze[0].lenght];
if(findPath(net, path, 0, 0))
{
Node temp;
while(!stack.isEmpty())
{
temp = stack.pop();
System.out.print("("+temp.coordinate[0]+" "+temp.coordinate[1]+") ");
}
}
else System.out.println("No Solution Possible.");
}
}
for this example the output should be:
(0 0) (1 0) (2 0) (3 0) (4 0) (4 4)
but I have this output:
(0 0) (0 1) (0 2) (0 3) (0 4) (1 4) (2 4) (3 4) (3 1) (3 2) (3 3) (4 3) (4 0) (4 4)
Please, any help how to fix the code so the solution will be the shortest path?!
After searching about BFS, now I know the difference between DFS and BFS.
DFS algorithm travels a path from the source to the last node, if the goal is found stop, else try another path again from the source to the last node, and so until the goal is reached. While BFS algorithm travels from the source to the level below, if the goal is found stop, else go to the next level and so on..
For my problem, BFS is a suitable algorithm to find the shortest path.
The code after some modifications:
public class findShoretstPath
{
private static class Node
{
private int[] coordinate = new int[2];
private int data;
private Node Right, Left, Top, Bottom;
public Node(){}
}
public static boolean isLinked(Node s, Node d) //method to determine if the node d is linked to the node s
{
if(d.Right == s) return true;
if(d.Bottom == s) return true;
if(d.Left == s) return true;
if(d.Top == s) return true;
return false;
}
public static boolean isValid(int[][] a, int x, int y)
{
if(x >= 0 && x < a.length && y >= 0 && y < a.length)
return true;
return false;
}
public static Node[][] nodeArray(int[][] a)
{
Node[][] nodeA = new Node[a.length][a.length];
for(int i = 0; i<nodeA.length; i++)
for(int j = 0; j<nodeA[i].length; j++)
{
nodeA[i][j] = new Node();
nodeA[i][j].coordinate[0] = i;
nodeA[i][j].coordinate[1] = j;
nodeA[i][j].data = a[i][j];
}
for(int i = 0; i<nodeA.length; i++)
for(int j = 0; j<nodeA[i].length; j++)
{
if(isValid(a, i, j+nodeA[i][j].data))
nodeA[i][j].Right = nodeA[i][j+nodeA[i][j].data];
if(isValid(a, i, j-nodeA[i][j].data))
nodeA[i][j].Left = nodeA[i][j-nodeA[i][j].data];
if(isValid(a, i+nodeA[i][j].data, j))
nodeA[i][j].Bottom = nodeA[i+nodeA[i][j].data][j];
if(isValid(a, i-nodeA[i][j].data, j))
nodeA[i][j].Top = nodeA[i-nodeA[i][j].data][j];
}
return nodeA;
}
public static void shortestPath(Node[][] nodes, int x, int y)
{
Stack<Node> stack = new Stack<>();
Queue<Node> queue = new LinkedList<>();
int[][] path = new int[nodes.length][nodes[0].length];
boolean b = false;
int level = 1;//to keep tracking each level viseted
queue.add(nodes[x][y]);
path[x][y] = level;
while(!queue.isEmpty())
{
Node temp;
level++;
int size = queue.size();
for(int i = 0; i<size; i++)
{
temp = queue.remove();
if(temp.data == -1) {b = true; break;}
if(temp.Right != null && path[temp.Right.coordinate[0]][temp.Right.coordinate[1]] == 0)
{
queue.add(temp.Right);
path[temp.Right.coordinate[0]][temp.Right.coordinate[1]] = level;
}
if(temp.Bottom != null && path[temp.Bottom.coordinate[0]][temp.Bottom.coordinate[1]] == 0)
{
queue.add(temp.Bottom);
path[temp.Bottom.coordinate[0]][temp.Bottom.coordinate[1]] = level;
}
if(temp.Left != null && path[temp.Left.coordinate[0]][temp.Left.coordinate[1]] == 0)
{
queue.add(temp.Left);
path[temp.Left.coordinate[0]][temp.Left.coordinate[1]] = level;
}
if(temp.Top != null && path[temp.Top.coordinate[0]][temp.Top.coordinate[1]] == 0)
{
queue.add(temp.Top);
path[temp.Top.coordinate[0]][temp.Top.coordinate[1]] = level;
}
}
if(b) break;
}
if(b)
{
int x1 = 0, y1 = 0;
for(int i = 0; i<nodes.length; i++)// to locate the position of the goal
for(int j = 0; j<nodes.length; j++)
if(nodes[i][j].data == -1)
{
x1 = i; y1 = j;
}
stack.add(nodes[x1][y1]);
int d = path[x1][y1];
while(d > 0)//go back from the goal to the source
{
for(int i = 0; i<path.length; i++)
{
if(path[x1][i] == d-1 && isLinked(nodes[x1][y1], nodes[x1][i]))
{
stack.add(nodes[x1][i]);
y1 = i;
break;
}
else if(path[i][y1] == d-1 && isLinked(nodes[x1][y1], nodes[i][y1]))
{
stack.add(nodes[i][y1]);
x1 = i;
break;
}
}
d--;
}
Node temp;
int stackSize = stack.size();
for(int i = 0; i<stackSize; i++)// print the final result
{
temp = stack.pop();
System.out.print("("+temp.coordinate[0]+" "+temp.coordinate[1]+") ");
}
}
else System.out.print("No Solution Possible.");
}
public static void main(String[] args)
{
int[][] maze = {{1,1,1,1,1},
{1,1,1,1,1},
{1,1,1,1,1},
{1,1,1,1,3},
{4,1,1,3,-1}};
Node[][] net = nodeArray(maze);
shortestPath(net, 0, 0));
System.out.println("");
}
}
and the output now is:
(0 0) (1 0) (2 0) (3 0) (4 0) (4 4)

IF Statement Checking (Not Working Properly)

randomEmpty() returns a random coordinate on the n x n grid that is empty (Method works). randomAdjacent() uses randomEmpty() to select an EMPTY coordinate on the map. Comparisons are then made to see if this coordinate has an VALID adjacent coordinate that is NON-EMPTY. The PROBLEM is that randomAdjacent does not always return the coordinates of space with an adjacent NON-EMPTY space. It will always return valid coordinates but not the latter. I can't spot the problem. Can someone help me identify the problem?
public int[] randomEmpty()
{
Random r = new Random();
int[] random = new int[2];
int row = r.nextInt(array.length);
int column = r.nextInt(array.length);
while(!(isEmpty(row,column)))
{
row = r.nextInt(array.length);
column = r.nextInt(array.length);
}
random[0] = row+1;
random[1] = column+1;
return random;
}
public int[] randomAdjacent()
{
int[] adjacentToX = new int[8];
int[] adjacentToY = new int[8];
int[] adjacentFrom = randomEmpty();
int count;
boolean isTrue = false;
boolean oneAdjacentNotEmpty = false;
while(!(oneAdjacentNotEmpty))
{
count = 0;
if(validIndex(adjacentFrom,1,-1))
{
adjacentToX[count] = adjacentFrom[0]+1;
adjacentToY[count] = adjacentFrom[1]-1;
count++;
}
if(validIndex(adjacentFrom,0,-1))
{
adjacentToX[count] = adjacentFrom[0];
adjacentToY[count] = adjacentFrom[1]-1;
count++;
}
if(validIndex(adjacentFrom,-1,-1))
{
adjacentToX[count] = adjacentFrom[0]-1;
adjacentToY[count] = adjacentFrom[1]-1;
count++;
}
if(validIndex(adjacentFrom,-1,0))
{
adjacentToX[count] = adjacentFrom[0]-1;
adjacentToY[count] = adjacentFrom[1];
count++;
}
if(validIndex(adjacentFrom,-1,1))
{
adjacentToX[count] = adjacentFrom[0]-1;
adjacentToY[count] = adjacentFrom[1]+1;
count++;
}
if(validIndex(adjacentFrom,0,1))
{
adjacentToX[count] = adjacentFrom[0];
adjacentToY[count] = adjacentFrom[1]+1;
count++;
}
if(validIndex(adjacentFrom,1,1))
{
adjacentToX[count] = adjacentFrom[0]+1;
adjacentToY[count] = adjacentFrom[1]+1;
count++;
}
if(validIndex(adjacentFrom,1,0))
{
adjacentToX[count] = adjacentFrom[0]+1;
adjacentToY[count] = adjacentFrom[1];
count++;
}
for(int i = 0; i < count; i++)
{
if(!(isEmpty(adjacentToX[i],adjacentToY[i])))
{
oneAdjacentNotEmpty = true;
isTrue = true;
}
}
if(isTrue)
break;
else
adjacentFrom = randomEmpty();
}
return adjacentFrom;
}
public boolean validIndex(int[] a,int i, int j)
{
try
{
Pebble aPebble = array[a[0]+i][a[1]+j];
return true;
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
}
public void setCell(int xPos, int yPos, Pebble aPebble)
{
array[xPos-1][yPos-1] = aPebble;
}
public Pebble getCell(int xPos, int yPos)
{
return array[xPos-1][yPos-1];
}
JUNIT Test Performed:
#Test
public void testRandomAdjacent() {
final int size = 5;
final Board board2 = new Board(size);
board2.setCell(1, 1, Pebble.O);
board2.setCell(5, 5, Pebble.O);
int[] idx = board2.randomAdjacent();
int x = idx[0];
int y = idx[1];
boolean empty = true;
for (int i = x - 1; i <= x + 1; i++) {
for (int j = y - 1; j <= y + 1; j++) {
if ((i == x && j == y) || i < 1 || j < 1 || i > size || j > size) {
continue;
}
if (board2.getCell(i, j) != Pebble.EMPTY)
empty = false;
}
}
assertFalse(empty);// NEVER gets SET TO FALSE
assertEquals(Pebble.EMPTY, board2.getCell(x, y));
}
As for the answer: I got carried away optimizing your code for readability. I'd think it's most likely
if (board2.getCell(i, j) != Pebble.EMPTY)
empty = false;
causing the problem as getCell operates in 1-based coordinates, but i, j are in 0-based.
You should think about your logic overall. The way I see it, your code might never terminate as randomEmpty() could keep returning the same field over and over again for an undetermined period of time.
I took the liberty to recode your if-if-if cascade into utility method easier to read:
public boolean hasNonEmptyNeighbor(int[] adjacentFrom) {
for(int i = -1; i <= 1; ++i) {
for(int j = -1; j <= 1; ++j) {
if(validIndex(adjacentFrom, i, j) //Still inside the board
&& // AND
!isEmpty(adjacentFrom[0]+i //not empty
,adjacentFrom[1]+j)) {
return true;
}
}
}
return false;
}
Given my previous comment about random() being not the best of choices if you need to cover the full board, your main check (give me an empty cell with a non-empty neighbor) could be rewritten like this:
public void find() {
List<Point> foundPoints = new ArrayList<Point>();
for(int i = 0; i < Board.height; ++i) { //Assumes you have stored your height
for(int j = 0; j < Board.width; ++j) { //and your width
if(isEmpty(i, j) && hasNonEmptyNeighbor(new int[]{i,j})) {
//Found one.
foundPoints.add(new Point(i, j));
}
}
}
//If you need to return a RANDOM empty field with non-empty neighbor
//you could randomize over length of foundPoints here and select from that list.
}

Keeping track of Collisions per index in an array-based hash table, as well as which values resulted in a collision using OPEN ADDRESSING ONLY

Sorry for the wordy title but it explains my question pretty well.
I am working on an assignment in Java where I need to create my own Hash Table.
The specifications are such that I must use an Array, as well as open-addressing for collision handling (with both double hashing and quadratic hashing implementations).
My implementation works quite well, and using over 200,000 randomly generated Strings I end up with only ~1400 Collisions with both types of collision handling mentioned about (keeping my load factor at 0.6 and increasing my Array by 2.1 when it goes over).
Here is where I'm stumped, however... My assignment calls for 2 specifications that I cannot figure out.
1) Have an option which, when removing a value form the table, instead of using "AVAILABLE" (replacing the index in the array with a junk value that indicates it is empty), I must find another value that previously hashed to this index and resulted in a collision. For example, if value A hashed to index 2 and value B also hashed to index 2 (and was later re-hashed to index 5 using my collision handling hash function), then removing value A will actually replace it with Value B.
2) Keep track of the maximum number of collisions in a single array index. I currently keep track of all the collisions, but there's no way for me to keep track of the collisions at an individual cell.
I was able to solve this problem using Separate Chaining by having each Array Index hold a linked list of all values that have hashed to this index, so that only the first one is retrieved when I call my get(value) method, but upon removal I can easily replace it with the next value that hashed to this index. It's also an easy way to get the max number of collisions per index.
But we were specifically told not to use separate chaining... I'm actually wondering if this is even possible without completely ruining the complexity of the hash table.
Any advice would be appreciated.
edit:
Here are some examples to give you an idea of my class structure:
public class daveHash {
//Attributes
public String[] dTable;
private double loadFactor, rehashFactor;
private int size = 0;
private String emptyMarkerScheme;
private String collisionHandlingType;
private int collisionsTotal = 0;
private int collisionsCurrent = 0;
//Constructors
public daveHash()
{
dTable = new String[17];
rehashFactor = 2.1;
loadFactor = 0.6;
emptyMarkerScheme = "A";
collisionHandlingType = "D";
}
public daveHash(int size)
{
dTable = new String[size];
rehashFactor = 2.1;
loadFactor = 0.6;
emptyMarkerScheme = "A";
collisionHandlingType = "D";
}
My hashing functions:
public long getHashCode(String s, int index)
{
if (index > s.length() - 1)
return 0;
if (index == s.length()-1)
return (long)s.charAt(index);
if (s.length() >= 20)
return ((long)s.charAt(index) + 37 * getHashCode(s, index+3));
return ((long)s.charAt(index) + 37 * getHashCode(s, index+1));
}
public int compressHashCode(long hash, int arraySize)
{
int b = nextPrime(arraySize);
int index = ((int)((7*hash) % b) % arraySize);
if (index < 0)
return index*-1;
else
return index;
}
Collision handling:
private int collisionDoubleHash(int index, long hashCode, String value, String[] table)
{
int newIndex = 0;
int q = previousPrime(table.length);
int secondFunction = (q - (int)hashCode) % q;
if (secondFunction < 0)
secondFunction = secondFunction*-1;
for (int i = 0; i < table.length; i++)
{
newIndex = (index + i*secondFunction) % table.length;
//System.out.println(newIndex);
if (isAvailable(newIndex, table))
{
table[newIndex] = value;
return newIndex;
}
}
return -1;
}
private int collisionQuadraticHash(int index, long hashCode, String value, String[] table)
{
int newIndex = 0;
for (int i = 0; i < table.length; i ++)
{
newIndex = (index + i*i) % table.length;
if (isAvailable(newIndex, table))
{
table[newIndex] = value;
return newIndex;
}
}
return -1;
}
public int collisionHandling(int index, long hashCode, String value, String[] table)
{
collisionsTotal++;
collisionsCurrent++;
if (this.collisionHandlingType.equals("D"))
return collisionDoubleHash(index, hashCode, value, table);
else if (this.collisionHandlingType.equals("Q"))
return collisionQuadraticHash(index, hashCode, value, table);
else
return -1;
}
Get, Put and Remove:
private int getIndex(String k)
{
long hashCode = getHashCode(k, 0);
int index = compressHashCode(hashCode, dTable.length);
if (dTable[index] != null && dTable[index].equals(k))
return index;
else
{
if (this.collisionHandlingType.equals("D"))
{
int newIndex = 0;
int q = previousPrime(dTable.length);
int secondFunction = (q - (int)hashCode) % q;
if (secondFunction < 0)
secondFunction = secondFunction*-1;
for (int i = 0; i < dTable.length; i++)
{
newIndex = (index + i*secondFunction) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return newIndex;
}
}
}
else if (this.collisionHandlingType.equals("Q"))
{
int newIndex = 0;
for (int i = 0; i < dTable.length; i ++)
{
newIndex = (index + i*i) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return newIndex;
}
}
}
return -1;
}
}
public String get(String k)
{
long hashCode = getHashCode(k, 0);
int index = compressHashCode(hashCode, dTable.length);
if (dTable[index] != null && dTable[index].equals(k))
return dTable[index];
else
{
if (this.collisionHandlingType.equals("D"))
{
int newIndex = 0;
int q = previousPrime(dTable.length);
int secondFunction = (q - (int)hashCode) % q;
if (secondFunction < 0)
secondFunction = secondFunction*-1;
for (int i = 0; i < dTable.length; i++)
{
newIndex = (index + i*secondFunction) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return dTable[newIndex];
}
}
}
else if (this.collisionHandlingType.equals("Q"))
{
int newIndex = 0;
for (int i = 0; i < dTable.length; i ++)
{
newIndex = (index + i*i) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return dTable[newIndex];
}
}
}
return null;
}
}
public void put(String k, String v)
{
double fullFactor = (double)this.size / (double)dTable.length;
if (fullFactor >= loadFactor)
resizeTable();
long hashCode = getHashCode(k, 0);
int index = compressHashCode(hashCode, dTable.length);
if (isAvailable(index, dTable))
{
dTable[index] = v;
size++;
}
else
{
collisionHandling(index, hashCode, v, dTable);
size++;
}
}
public String remove(String k)
{
int index = getIndex(k);
if (dTable[index] == null || dTable[index].equals("AVAILABLE") || dTable[index].charAt(0) == '-')
return null;
else
{
if (this.emptyMarkerScheme.equals("A"))
{
String val = dTable[index];
dTable[index] = "AVAILABLE";
size--;
return val;
}
else if (this.emptyMarkerScheme.equals("N"))
{
String val = dTable[index];
dTable[index] = "-" + val;
size--;
return val;
}
}
return null;
}
Hopefully this can give you an idea of my approach. This does not include the Separate Chaining implementation I mentioned above. For this, I had the following inner classes:
private class hashList
{
private class hashNode
{
private String element;
private hashNode next;
public hashNode(String element, hashNode n)
{
this.element = element;
this.next = n;
}
}
private hashNode head;
private int length = 0;
public hashList()
{
head = null;
}
public void addToStart(String s)
{
head = new hashNode(s, head);
length++;
}
public int getLength()
{
return length;
}
}
And my methods were modified appropriate to access the element in the head node vs the element in the Array. I took this out, however, since we are not supposed to use Separate Chaining to solve the problem.
Thanks!!

Fixing a PathFinding code

I have this path finding code which does the first part of the finding by only going one square
public class PathFinding {
static Vector2 start;
static Vector2 end;
static Cell[][] cells;
static Node currentNode;
static Arena arena;
public static void calcPAth(Vector2 from, Vector2 to,
Cell[][] mapCells, Arena a) {
start = from;
end = to;
cells = mapCells;
arena = a;
List<Node> openList = new ArrayList<Node>();
List<Node> closedList = new ArrayList<Node>();
Gdx.app.log(PArena.LOG, "Lists Created");
currentNode = new Node(null, start);
openList.add(currentNode);
Gdx.app.log(PArena.LOG, "Added start to openList");
// check squares around this and add
int startPX = (int) currentNode.parentV.x / 32;
Gdx.app.log(PArena.LOG, "Start X" + startPX);
int startPY = (int) currentNode.parentV.y / 32;
Gdx.app.log(PArena.LOG, "Start Y" + startPY);
Gdx.app.log("", "");
//
int MIN_X = startPX - 1;
int MIN_Y = startPY - 1;
int MAX_X = startPX + 1;
int MAX_Y = startPY + 1;
int startPosX = (startPX - 1 < MIN_X) ? startPX : startPX - 1;
int startPosY = (startPY - 1 < MIN_Y) ? startPY : startPY - 1;
int endPosX = (startPX + 1 > MAX_X) ? startPX : startPX + 1;
int endPosY = (startPY + 1 > MAX_Y) ? startPY : startPY + 1;
// Check boundaries on start cell
for (int rowNum = startPosX; rowNum <= endPosX; rowNum++) {
for (int colNum = startPosY; colNum <= endPosY; colNum++) {
// All the neighbors will be grid[rowNum][colNum]
if (!cells[rowNum][colNum].getTile().getProperties()
.containsKey("blocked")) {
Node node = new Node(currentNode, new Vector2(
rowNum, colNum));
if (rowNum != startPX && colNum != startPY) {
node.setMovementCost(14);
} else
node.setMovementCost(10);
openList.add(node);
System.out.print(node.getFValue() + "|");
} else
System.out.print("B");
}
System.out.println("");
}
openList.remove(currentNode);
closedList.add(currentNode);
int n = openList.get(0).getFValue();
int index = 0;
for (Node temp : openList) {
if (temp.getFValue() < n) {
n = temp.getFValue();
index = openList.lastIndexOf(temp);
Gdx.app.log("n", "n = " + n);
}
}
currentNode = openList.get(index);
arena.colorSquare(currentNode.getVectorPos());
// need to calc move cost;
//
Gdx.app.log("", "");
openList.clear();
closedList.clear();
}
This is my Node class
public static class Node {
int hVal;
int gVal;
int fVal;
Node parentNode;
Vector2 parentV;
private Node(Node node, Vector2 p) {
setParent(node);
this.parentV = p;
calcHValue();
}
public void setMovementCost(int c) {
this.gVal = c;
calcFVal();
}
private void calcFVal() {
fVal = gVal + hVal;
// Gdx.app.log("Node", "HVal = " + hVal);
// Gdx.app.log("Node", "GVal = " + gVal);
// Gdx.app.log("Node", "FVal = " + fVal);
}
private void calcHValue() {
int x = (int) (parentV.x - end.x);
if (x < 0)
x *= -1;
int y = (int) (parentV.y - end.y);
if (y < 0)
y *= -1;
hVal = (int) (x + y) / 32;
// Gdx.app.log(PArena.LOG, "Heuristic Value" + hVal);
}
private void setParent(Node node) {
this.parentNode = node;
}
public int getFValue() {
return fVal;
}
public Vector2 getVectorPos() {
return parentV;
}
}
My problem is that my debugging outputs like this
15|11|15|
11|11|11|
15|11|15|
So basically it isnt actually calculating the total value. It is just adding the movement cost, not heuristic.
What is th problem? Am i missing a step?
You are missing the Successor list i think. An A* does have a Successorlist and while the openlist isnt empty you do the following stuff:
while (openList.size() != 0) {
successor.clear();
q = openList.remove(); //first element of the prio queue
// generate your neighbornodes of q and add them to the successorlist
//after this you iterate over the successor and check if its your goalnode.
//If so you do return it else you add it to the openlist. (still inside of the while!)
//Dont forget to check if the neighbor is inside of the close list!
//if so you do not need to add it to the successorlist
//Here is how it does look at mine A*. It also contains a check if there is a betterone
// calc
for (Node suc : successor) {
if (suc.x == (int) this.screen.character.mapPos.x
&& suc.y == (int) this.screen.character.mapPos.y)
return suc; //return the goalnode
boolean add = true;
if (betterIn(suc, openList))
add = false;
if (betterIn(suc, closeList))
add = false;
if (add)
openList.add(suc);
}
Last but not least you do delete the q note from the openlist and add it to the close ist.
}
closeList.add(q);
}//end of while
Some more minor improvmements would be that you do add a compareable to the Node..
#Override
public int compareTo(Node o) {
if ((this.g + this.h) < (o.g + o.h))
return -1;
else if ((this.g + this.h) >= (o.g + o.h))
return 1;
else
return 0;
}
also override the equals and the hashCode method for it for example like this:
#Override
public boolean equals(Object o) {
// override for a different compare
return ((Node) o).x == this.x && ((Node) o).y == this.y;
}
#Override
public int hashCode() {
return x + y;
}
After that your openList can be a PriorityQueue<Node> and the first object you are getting from the is always the one with the smallest h.
Dont forget to return our final Node to iterate over the getparent method to get the path.
private boolean betterIn(Node n, Collection<Node> l) {
for (Node no : l) {
if (no.x == n.x && no.y == n.y && (no.g + no.h) <= (n.g + n.h))
return true;
}
return false;
}

Categories

Resources