Implementing a heap - java

I am trying to implement a heap data structure, i wrote the maxHeapify method which builda maximum heap, and used it in my insert method in which i insert at the end then rearrange the heap to remain a max heap.
but it doesn't appear to work, any help would be appreciated.
public class Heap { // a class to implement a heap
private int[] data; // the heap array
private static final int FRONT = 1;
private int maxSize = 0;
private int currentSize; // the current size of the data in the array
public Heap(int maxSize) {
this.currentSize = 1;
this.maxSize = maxSize;
data = new int[maxSize + 1];
}
public int[] getData() {
return data;
}
public void setData(int[] data) {
this.data = data;
}
public int getMaxSize() {
return maxSize;
}
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
public int getCurrentSize() {
return currentSize;
}
public void setCurrentSize(int currentSize) {
this.currentSize = currentSize;
}
#SuppressWarnings("unused")
private int parent(int index) {// the index of the parent
return index / 2;
}
private int left(int index) { // the index of the left child
return (2 * index);
}
private int right(int index) { // the index of the right child
return (2 * index) + 1;
}
private void swap(int i, int j) { // to swap two elements
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
private void maxHeapify(int i) { // to build a max heap
int left = left(i); // a method to return the index of the left child
int right = right(i);// a method to return the index of the right child
int largest = i;
int x = currentSize;
if (left <= currentSize && data[left] > data[i]) {
largest = left;
}
if (right <= currentSize && data[right] > data[largest]) {
largest = right;
}
if (largest != i) {
int temp = data[i];
data[i] = data[largest];
data[largest] = temp;
maxHeapify(largest);
}
}
public void maxHeap() {
for (int i = currentSize / 2; i >= 1; i--) {
maxHeapify(i);
}
}
public void insert(int newData) { // insert to the heap
data[currentSize] = newData;
currentSize++;
maxHeapify(FRONT);
}
public int deleteMax() { // delete max from the heap
int maxValue = data[FRONT];
data[FRONT] = data[data.length - 1];
maxHeapify(FRONT);
currentSize--;
return maxValue;
}
public void sort() {// heap sort
maxHeap();
for (int i = maxSize; i > 1; i--) {
swap(FRONT, maxSize);
maxSize--;
maxHeapify(FRONT);
}
}
public void clear() {
maxSize = 0;
}
public boolean isEmpty() {
return maxSize == 0;
}
public boolean isFull() {
return currentSize == data.length;
}
public void printHeap() {// prints the heap
for (int i = 1; i <= maxSize / 2; i++) {
System.out.print(
" PARENT : " + data[i] + " LEFT CHILD : " + data[2 * i] + " RIGHT CHILD :" + data[2 * i + 1]);
System.out.println();
}
}
}

Your function maxHeapify works when you add new number on root of your heap. I mean to say in maxHeapify, you are moving from root to child. But during insertion you are inserting element to the last. You have to move from down to up.
maxHeapify : going root to down.
After inserting element to data array, you have to check upward from child to parent exact opposite of maxHeapify.

This should work:
/**
* Parent.
*
* #param pos the pos
* #return the int
*/
private int parent(int pos)
{
return pos / 2;
}
/**
* Left.
*
* #param pos the pos
* #return the int
*/
private int left(int pos)
{
return (2 * pos);
}
/**
* Right.
*
* #param pos the pos
* #return the int
*/
private int right(int pos)
{
return (2 * pos) + 1;
}
/**
* Checks if is leaf.
*
* #param pos the pos
* #return true, if is leaf
*/
private boolean isLeaf(int pos)
{
if (pos >= (size / 2) && pos <= size)
{
return true;
}
return false;
}
/**
* Swap.
*
* #param fpos the fpos
* #param spos the spos
*/
private void swap(int fpos,int spos)
{
int tmp;
tmp = data[fpos];
data[fpos] = data[spos];
data[spos] = tmp;
}
/**
* Max heapify.
*
* #param pos the pos
*/
private void maxHeapify(int pos)
{
if (!isLeaf(pos))
{
if ( data[pos] < data[left(pos)] || data[pos] < data[right(pos)])
{
if (data[left(pos)] > data[right(pos)])
{
swap(pos, left(pos));
maxHeapify(left(pos));
}else
{
swap(pos, right(pos));
maxHeapify(right(pos));
}
}
}
}
/**
* Insert.
*
* #param newElement the element
*/
public void insert(int newElement)
{
data[++size] = newElement;
int current = size;
while(data[current] > data[parent(current)])
{
swap(current,parent(current));
current = parent(current);
}
}

You required to shift up after adding the new element at last position.
For an example.
public void insert(int value) {
if (heapSize == data.length)
throw new HeapException( storage is overflow");
else {
heapSize++;
data[heapSize - 1] = value;
siftUp(heapSize - 1);
}
}
private void siftUp(int nodeIndex) {
//code to hepify.
}

Related

Max Heap MaxHeapify Java Not finishing

Having trouble with the constructor for MaxHeapify when there are more than 2 numbers that need to be ordered. stepping thru the code, it works for the first few and then continues without properly ordering the numbers.
i am not sure why this isn't working, any assistance on which variables or comparisons I seem to be mixing up here would be much appreciated.
public class MaxHeap
{
public int[] heap;
public int index_to_last_element;
protected void maxHeapify(int index)
{
int left = leftchild(index);
int right = rightchild(index);
int largest = index;
if (left < index_to_last_element && left != -1 && heap[left] > heap[index])
largest = left;
if (right < index_to_last_element && right != -1 && heap[right] > heap[largest])
largest = right;
if (largest != index)
{
int temp = heap[index];
heap[index] = heap[largest];
heap[largest] = temp;
maxHeapify(largest);
}
}
public int parent(int pos)
{
return (pos - 1) / 2;
}
public int leftchild(int pos)
{
return 2 * pos + 1;
}
public int rightchild(int pos)
{
return 2 * pos + 2;
}

QuickSort for big cases leads to stackoverflow

I am working on a school project that has to have 3 quicksorts with 1 pointer, 3 quicksorts with 2 pointers and 2 heaps.
I wrote the Quicksorts and one of the heaps so far.
The problem I have is quicksort works fine in small cases however in larger cases I get a stackoverflow.
Nore: each quicksort has an easy case in which it should run insertion sort.
Why do i get stack a overflow?
package prog3;
import java.util.Random;
public class ArraySorts {
public static void QuickSort1(int[] a, int n) {
QuickSort1(a, 0, n - 1);
}
private static void QuickSort1(int[] a, int start, int end) {
if ((end - start+1) <= 20) {
int num = (end + 1) - start;
insertion(a, num);
}
else {
// use first element as division between small and big
Random rand = new Random();
int pivotIndex = start + rand.nextInt(end - start);
swap(a, pivotIndex, start);
int pivot = a[start];
int partitionBook = partitionBook(a, start, end, pivot);
// recursively sort the smalls and then the bigs
QuickSort1(a, start, partitionBook - 1);
QuickSort1(a, partitionBook + 1, end);
}
}
public static void QuickSort2(int[] a, int n) {
// 2 ptr partition, random pivot, easiest case = 20
int left = 0;
int right = n - 1;
QuickSort2(a, left, right);
}
public static void QuickSort2(int[] a, int left, int right) {
if ((right - left + 1) <= 20) {
int num = right - left + 1;
insertion(a, num);
} else {
// int pivot = a[right];
Random rand = new Random();
int pivotIndex = left + rand.nextInt(right - left + 1);
swap(a, pivotIndex, right);
int pivot = a[right];
int partition = partition(a, left, right, pivot);
QuickSort2(a, 0, partition - 1);
QuickSort2(a, partition + 1, right);
}
}
public static void QuickSort3(int[] a, int n) {
QuickSort3(a, 0, n - 1);
}
private static void QuickSort3(int[] a, int start, int end) {
if ((end - start) <= 20) {
int num = (end + 1) - start;
insertion(a, num);
}
else {
// use first element as division between small and big
int pivot = a[start];
int partitionBook = partitionBook(a, start, end, pivot);
// recursively sort the smalls and then the bigs
QuickSort3(a, start, partitionBook - 1);
QuickSort3(a, partitionBook + 1, end);
}
}
public static void QuickSort4(int[] a, int n) {
// 2 ptr partition, random pivot, easiest case = 1
int left = 0;
int right = n - 1;
QuickSort4(a, left, right);
}
public static void QuickSort4(int[] a, int left, int right) {
if ((right - left + 1) <= 1) {
return;
}
// int pivot = a[right];
Random rand = new Random();
int pivotIndex = left + rand.nextInt(right - left + 1);
swap(a, pivotIndex, right);
int pivot = a[right];
// System.out.println("Pivot: " + pivot);
int partition = partition(a, left, right, pivot);
QuickSort4(a, 0, partition - 1);
QuickSort4(a, partition + 1, right);
}
public static void QuickSort5(int[] a, int n) {
// 2 ptr partition, random pivot, easiest case = 500
int left = 0;
int right = n - 1;
QuickSort5(a, left, right);
}
public static void QuickSort5(int[] a, int left, int right) {
if ((right - left + 1) <= 500) {
int num = right - left + 1;
insertion(a, num);
} else {
// int pivot = a[right];
Random rand = new Random();
int pivotIndex = left + rand.nextInt(right - left + 1);
swap(a, pivotIndex, right);
int pivot = a[right];
int partition = partition(a, left, right, pivot);
QuickSort5(a, 0, partition - 1);
QuickSort5(a, partition + 1, right);
}
}
public static void QuickSort6(int[] a, int n) {
QuickSort6(a, 0, n - 1);
}
private static void QuickSort6(int[] a, int start, int end) {
if ((end - start+1) <= 1) {
return;
}
else {
// use first element as division between small and big
Random rand = new Random();
int pivotIndex = start + rand.nextInt(end - start);
swap(a, pivotIndex, start);
int pivot = a[start];
int partitionBook = partitionBook(a, start, end, pivot);
// recursively sort the smalls and then the bigs
QuickSort1(a, start, partitionBook - 1);
QuickSort1(a, partitionBook + 1, end);
}
}
private static int partition(int[] a, int left, int right, int pivot) {
int leftCursor = left - 1;
int rightCursor = right;
while (leftCursor < rightCursor) {
while (a[++leftCursor] < pivot)
;
while (rightCursor > 0 && a[--rightCursor] > pivot)
;
if (leftCursor > rightCursor) {
break;
} else {
swap(a, leftCursor, rightCursor);
}
}
swap(a, leftCursor, right);
return leftCursor;
}
private static int partitionBook(int[] a, int start, int end, int pivot) {
// the index of the last small element
int lastSmall = start;
for (int unknown = start + 1; unknown <= end; unknown++) {
// see if the current element is small
if (a[unknown] < pivot) {
// and if so, put it with the other smalls
lastSmall++;
int temp = a[lastSmall];
a[lastSmall] = a[unknown];
a[unknown] = temp;
}
}
// put the pivot between the smalls and the bigs
int temp = a[start];
a[start] = a[lastSmall];
a[lastSmall] = temp;
return lastSmall;
}
public static void swap(int[] a, int left, int right) {
int temp = a[left];
a[left] = a[right];
a[right] = temp;
}
public static void printArray(int[] a) {
for (int i : a) {
System.out.print(i + " ");
}
}
public static int[] getArray() {
int size = 10;
int[] array = new int[size];
int item = 0;
for (int i = 0; i < size; i++) {
item = (int) (Math.random() * 100);
array[i] = item;
}
return array;
}
/**
* Will return the left child's index
*
* #param iIndex
* The index of the current position (Parent)
* #return The index of the left child
*/
static int Left(int iIndex) {
return ((iIndex << 1) + 1);
}
/**
* Will return the right child's index
*
* #param iIndex
* The index of the current position (Parent)
* #return The index of the right child
*/
static int Right(int iIndex) {
return ((iIndex << 1) + 2);
}
/**
* Will return the parent of the current index
*
* #param iIndex
* The index of the current position (Child)
* #return The index of the parent
*/
int Parent(int iIndex) {
return ((iIndex - 1) >> 1);
}
/**
* Swaps the values of the two index locations
*
* #param firstIndex
* the index of the first number to exchange.
* #param secondIndex
* The index of the second number to exchange.
* #param ipHeap
*/
static void Swap(int firstIndex, int secondIndex, int[] ipHeap) {
int iTemp = ipHeap[firstIndex];
ipHeap[firstIndex] = ipHeap[secondIndex];
ipHeap[secondIndex] = iTemp;
}
/**
* Determines if there needs to have a swap of a child and parent. It will
* determine which child needs to be swapped.
*
* #param parent
* index of the parent (current index)
* #param ipHeap
* The array that needs the operations performed.
* #param iSize
* The adjusted size of the array
* #return The index of the largest value.
*/
static int SwapWithChild(int parent, int[] ipHeap, int iSize) {
int leftChild = Left(parent);
int rightChild = Right(parent);
int iLargest = parent;
if (rightChild < iSize) {
if (ipHeap[leftChild] < ipHeap[rightChild]) {
iLargest = rightChild;
} else {
iLargest = leftChild;
}
if (ipHeap[parent] > ipHeap[iLargest]) {
iLargest = parent;
}
} else if (leftChild < iSize) {
if (ipHeap[parent] < ipHeap[leftChild]) {
iLargest = leftChild;
}
}
if (ipHeap[parent] < ipHeap[iLargest]) {
Swap(parent, iLargest, ipHeap);
}
return iLargest;
}
/**
* Replaces the value of the root with the value of the last element of the
* heap.
*
* #param ipHeap
* The heap to have the root replaced.
* #param iSize
* The size of the heap.
*/
void RemoveRoot(int[] ipHeap, int iSize) {
// Put the last element at the root
ipHeap[0] = ipHeap[iSize - 1];
--iSize;
int iLasti = 0;
int i = SwapWithChild(0, ipHeap, iSize);
while (i != iLasti) {
iLasti = i;
i = SwapWithChild(i, ipHeap, iSize);
}
}
/**
* Exchanges the current index value with that of the parent
*
* #param i
* The index of the current value (Child).
* #param ipHeap
* The heap being working with.
* #return
*/
int SwapWithParent(int i, int[] ipHeap) {
if (i < 1) {
return i;
}
int iParent = Parent(i);
if (ipHeap[i] > ipHeap[iParent]) {
Swap(i, iParent, ipHeap);
return iParent;
} else {
return i;
}
}
/**
* Adds an element to the provided heap
*
* #param iNewEntry
* The value being added to the heap.
* #param ipHeap
* The heap to add the new value.
* #param iSize
* The current size of the heap.
*/
void AddElement(int iNewEntry, int[] ipHeap, int iSize) {
ipHeap[iSize] = iNewEntry;
int iLasti = iSize;
int i = SwapWithParent(iLasti, ipHeap);
while (iLasti != i) {
iLasti = i;
i = SwapWithParent(i, ipHeap);
}
}
/**
* Displays the heap to the console in a linear fashion.
*
* #param ipArray
* The heap to be displayed.
* #param iSize
* The current size of the heap.
*/
static void OutputArray(int[] ipArray, int iSize, int verticalBar) {
for (int i = 0; i < iSize; ++i) {
if (i == verticalBar) {
System.out.print("| ");
}
System.out.print(ipArray[i] + " ");
}
System.out.println();
}
/**
* Sorts the heap
*
* #param ipHeap
* The heap that needs to be sorted.
* #param iSize
* The current size of the heap.
*/
static void sortRoot(int[] ipHeap, int iSize) {
// Swap the last element with the root
Swap(0, iSize - 1, ipHeap);
iSize--;
int iLasti = 0;
int i = SwapWithChild(0, ipHeap, iSize);
while (i != iLasti) {
iLasti = i;
i = SwapWithChild(i, ipHeap, iSize);
}
}
static void heapify(int[] a) {
for (int iLast = a.length >> 1; iLast >= 0; iLast--) {
int i = SwapWithChild(iLast, a, a.length);
while (iLast != i) {
iLast = i;
i = SwapWithChild(i, a, a.length);
}
}
}
static void HeapSort2(int[] a, int n) {
heapify(a);
for (int i = 0; i < n; ++i) {
sortRoot(a, n - i);
OutputArray(a, n, n - 1 - i);
System.out.println();
}
}
public static void HeapSort1(int[] a, int n){
int count =n;
//first place a in max-heap order
heapify(a, count);
int end = count - 1;
while(end > 0){
//swap the root(maximum value) of the heap with the
//last element of the heap
int tmp = a[end];
a[end] = a[0];
a[0] = tmp;
//put the heap back in max-heap order
siftDown(a, 0, end - 1);
//decrement the size of the heap so that the previous
//max value will stay in its proper place
end--;
}
}
public static void heapify(int[] a, int count){
//start is assigned the index in a of the last parent node
int start = (count - 2) / 2; //binary heap
while(start >= 0){
//sift down the node at index start to the proper place
//such that all nodes below the start index are in heap
//order
siftDown(a, start, count - 1);
start--;
}
//after sifting down the root all nodes/elements are in heap order
}
public static void siftDown(int[] a, int start, int end){
//end represents the limit of how far down the heap to sift
int root = start;
while((root * 2 + 1) <= end){ //While the root has at least one child
int child = root * 2 + 1; //root*2+1 points to the left child
//if the child has a sibling and the child's value is less than its sibling's...
if(child + 1 <= end && a[child] < a[child + 1])
child = child + 1; //... then point to the right child instead
if(a[root] < a[child]){ //out of max-heap order
int tmp = a[root];
a[root] = a[child];
a[child] = tmp;
root = child; //repeat to continue sifting down the child now
}else
return;
}
}
static void insertion(int[] a, int n) {
//System.out.println("********** INSERTION************");
if (a.length == 0)
return;
for (int i = 0; i < a.length; i++) {
insertionHelper(a, i);
//OutputArray(a, a.length, i);
}
}
/**
* A private helper method for the insertion sorting.
*
* #param iaArray
* Array to be sorted
* #param pointer
* the current element that needs to be inserted in the proper
* order.
*/
private static void insertionHelper(int[] a, int pointer) {
// verify pointer is not at the begining of the array
if (pointer <= 0)
return;
// if pointer' value is smaller than the previous element, we need to
// swap.
while (pointer > 0 && a[pointer] < a[pointer - 1]) {
Swap(pointer, pointer - 1, a);
pointer--;
}
}
public static String myName() {
return "some name";
}
}
The reason that you get stack overflow exception is because you call method QuickSort1 in QuickSort1 and there is a limit when you implement recursive function like that. You can increase your call stack size using -Xss command line arg like:
java -Xss4m

Java Antwalk - 2D Arrays

There is a 2D array with dimensions 9x9. The ant starts in cell (5,5) , or the center. It moves randomly north, south, east, or west. The ant stops walking when it falls off the grid. The space where it falls is marked by an X. In the matrix, it should display the amount of times the ant visited each cell and the number of moves the ant took to fall off.
I'm not sure where to start or how to go about it. Like how to make the north, south, west, east methods.
Here's what I have so far.
public static void main(String [] args)
{
int [][] grid = new int[9][9];
for (int r = 0; r< grid.length; r++)
{
for (int c = 0 ; c<grid[0].length; c++)
{
grid[r][c] = 0;
}
}
boolean test = true;
while(test)
{
int random = (int)Math.random()*4+1;
if (random == 1)
{
}
else if (random == 2)
{
}
else if (random == 3)
{
}
else if (random == 4)
{
}
}
}
You've got the right idea, now what you want to do is move in the direction specified by random, and increment the value in your array. Here is how I would do it.
int count = 0;
int x = 4;
int y = 4; // arrays are 0 based
while(true)
{
int random = (int)Math.random()*4+1;
if (random == 1)
{
x--; // move left
}
else if (random == 2)
{
x++; // move right
}
else if (random == 3)
{
y--; // move down
}
else if (random == 4)
{
y++; // move up
}
if(x < 0 || y < 0 || x >= grid.length || y >= grid[x].length) break;
count++;
grid[x][y]++;
}
System.out.println(count); // number of moves before it fell
Here is a random walk of an ant on the grid. See comments in the code. The ant walks STEPS on a predefined size grid.
import java.util.Random;
public class Ants {
/** height and width of the grid */
public static final int HEIGHT = 9 ;
public static final int WIDTH = 9 ;
/** NOVAL means "no value" */
public static final int NOVAL = -1;
/** world directions */
public static final int NORTH = 0 ;
public static final int WEST = 1 ;
public static final int SOUTH = 2 ;
public static final int EAST = 3 ;
/** how many steps for ant to walk */
public static final int STEPS = 10;
/** where does the ant start it's walk */
public static final int START_X = 5;
public static final int START_Y = 5;
/** printing related */
public static final String ANT = "ANT";
private static final Random random = new Random();
/** grid for ant to walk on */
static int[] grid;
/** get height of the grid */
static int getHeight() {
return HEIGHT;
}
/** get width of the grid */
static int getWidth() {
return WIDTH;
}
/** size of the grid */
static int getSize() {
return getWidth()*getHeight();
}
/** coordinates are converted to one dimension */
/** #return index from coordinates. */
static int idx(int x, int y) {
return y*getWidth() + x;
}
/** get x coordinate of idx */
static int x(int idx) {
return idx % getWidth();
}
/** get y coordinate of idx */
static int y(int idx) {
return (idx - x(idx)) / getWidth();
}
/** get cell */
static int getCell(int idx) {
return grid[idx];
}
static int getCell(int x, int y) {
return getCell(
idx(x,y));
}
static void setCell(int idx, int value) {
grid[idx] = value;
}
/** init array with some value */
private static void initArr(int[] arr, int value) {
for (int i = 0; i < arr.length; i++) {
arr[i] = value;
}
}
/**
* #return adjancted cells indexes.
*/
public static int[] adjanctedTo(int idx) {
int[] adj = new int[4];
initArr(adj, NOVAL);
int x = x(idx);
int y = y(idx);
/** Is North available? */
if (y - 1 >= 0) {
adj[NORTH] = idx(x,y-1);
}
/** West? */
if (x - 1 >= 0) {
adj[WEST] = idx(x-1, y);
}
/** South? */
if (y + 1 < getHeight()) {
adj[SOUTH] = idx(x,y+1);
}
/** East? */
if (x + 1 < getWidth()) {
adj[EAST] = idx(x+1, y);
}
return adj;
}
/** picks random value from array */
public static int pick(int[] arr) {
int ret = NOVAL;
int idx = random.nextInt(4);
for (int i = idx;; i++) {
if (NOVAL != arr[i]) {
ret = arr[i];
break;
}
if (3 == i) {
/** cycle if not yet found a NOVAL value in array */
i = 0;
}
}
return ret;
}
public static void main(String[] args) {
/** init grid */
grid = new int[getSize()];
int nextStep = NOVAL;
int current = idx(START_X, START_Y);
setVisited(current);
for (int s = 0; s < STEPS; s++) {
System.out.println("STEP "+s);
System.out.println(
"Standing #" + position(current) + ".");
printGrid(current);
nextStep = pick(
adjanctedTo(current));
System.out.println(
"Moving to " + position(nextStep));
setVisited(current);
printGrid(nextStep);
current = nextStep;
}
}
public static void setVisited(int idx) {
setCell(idx, getCell(idx)+1);
}
public static String position(int idx) {
return idx+"("+x(idx) + ";" + y(idx) +")";
}
public static void printGrid(int antPosition) {
for (int x = 0; x < getWidth(); x++) {
for (int y = 0; y < getHeight(); y++) {
if (idx(x,y) == antPosition) {
System.out.print(ANT);
} else {
System.out.format(
"%2d|",
getCell(x,y));
}
}
System.out.println();
}
}
}
public static void main(String[] args) {
String[][] sim = ant(3,3);
for (int i = 0; i < sim.length; i++) {
for (int j = 0; j < sim[i].length; j++) {
System.out.print(sim[i][j] + " ");
}
System.out.println();
}
}
static String[][] ant(int x, int y) {
if(x<0||x>=9||y<0||y>=9){
return null;
}
int[] rn = {-1, 1}; //next ant random direction , you can include 0 if you wanted
String[][] mat = new String[9][9];
for (int i = 0; i < 9; i++) {
Arrays.fill(mat[i], "0");//fill array with 0 to avoid null default value
}
int a = x, b = y; // a and b are the Cartesian coordinates of the ant
while (true) {
mat[a][b] = String.valueOf(Integer.parseInt(mat[a][b]) + 1);
int newx = a + rn[(int) (Math.random() * rn.length)];
int newy = b + rn[(int) (Math.random() * rn.length)];
//these are the ant new coordinates , we have to check them before going to them
if (newx < 0 || newx >= 9 || newy < 0 || newy >= 9) {
mat[a][b] = "X";
return mat;
}
a = newx;
b = newy;
}
}

Assistance with Circular Extended Array Deque

I'm trying to implement a Deque utilizing a circular array that extends when the array gets full. However, I am getting an IndexOutOfBoundsException. I think my issue is with the insertLast method. I've analyzed my code thoroughly and I cannot see what I am doing wrong. Any assistance would be greatly appreciated.
public class CircularExtendedArrayDeque
{
public static final int INIT_CAPACITY = 4; // initial array capacity
protected int capacity; // current capacity of the array
protected int front; // index of the front element
protected int rear; // index of the rear element
protected int[] A; // array deque
public CircularExtendedArrayDeque( ) // constructor method
{
A = new int[ INIT_CAPACITY ];
capacity = INIT_CAPACITY;
front = rear = 0;
}
/**
* Print the content of the deque
*
*/
public void printDeque( )
{
for ( int i = front; i != rear; i = (i+1) % capacity )
System.out.print( A[i] + " " );
System.out.println();
}
/**
* Print the content of the whole array
*
*/
public void printArray( )
{
for ( int i = 0; i < capacity; i++ )
System.out.print( A[i] + " " );
System.out.println();
}
// ***************************************
// DO NOT MODIFY THE CODE ABOVE THIS LINE.
// ADD YOUR CODE BELOW THIS LINE.
//
// ***************************************
/**
* Returns the number of items in this collection.
* #return the number of items in this collection.
*/
public int size()
{
// COMPLETE THIS METHOD
return (capacity - front + rear) % capacity;
}
/**
* Returns true if this collection is empty.
* #return true if this collection is empty.
*/
public boolean isEmpty()
{
// COMPLETE THIS METHOD
return front == rear;
}
/**
* Returns the first element of the deque
*
*/
public int getFirst() throws EmptyDequeException
{
// COMPLETE THIS METHOD
if(isEmpty()){
throw new EmptyDequeException("Deque is empty.");
}
return A[front % capacity];
}
/**
* Returns the last element of the deque
*
*/
public int getLast() throws EmptyDequeException
{
// COMPLETE THIS METHOD
if(isEmpty()){
throw new EmptyDequeException("Deque is empty.");
}
return A[(front + rear - 1) % capacity];
}
/**
* Inserts e at the beginning (as the first element) of the deque
*
*/
public void insertFirst( int e )
{
// COMPLETE THIS METHOD
rear++;
if(size() == capacity - 1){
capacity *= 2;
}
int[] B = new int[capacity];
for(int i = 0; i < size(); i++){
B[i] = A[i];
}
A = B;
for(int i = size(); i >= front; i--){
A[i+1] = A[i];
}
A[front] = e;
front = front % capacity;
System.out.println("Front: " + front + " & Rear:" + rear);
}
/**
* Inserts e at the end (as the last element) of the deque
*
*/
public void insertLast( int e )
{
// COMPLETE THIS METHOD
if(size() == capacity - 1){
capacity *= 2;
int[] B = new int[capacity];
for ( int i = front; i != rear; i = (i+1) % capacity )
B[i] = A[i];
/*
for(int i = 0; i < size(); i++){
B[i] = A[i];
}
*/
A = B;
A[rear++] = e;
}
else{
//System.out.println("Array Size = " + A.length);
A[rear++] = e;
}
System.out.println("Front: " + front + " & Rear:" + rear);
System.out.println("msg...size=" + size());
}
/**
* Removes and returns the first element of the deque
*
*/
public int removeFirst( ) throws EmptyDequeException
{
// COMPLETE THIS METHOD
int result = A[front];
A[front] = 0;
front = (front+1)%capacity;
if(isEmpty()){
throw new EmptyDequeException("Deque is empty.");
}
else if(capacity >= 4){
if(size() < capacity/2){
//System.out.println("msg...size = " + size());
capacity /= 2;
int[] B = new int[capacity];
int counter=0;
for(int i = front; i < front+size(); i++){
B[counter] = A[i%(capacity*2)];
counter++;
}
A = B;
front = 0;
rear = size()-1;
}
}
return result;
}
/**
* Removes and returns the last element of the deque
*
*/
public int removeLast( ) throws EmptyDequeException
{
// COMPLETE THIS METHOD
if(isEmpty()){
throw new EmptyDequeException("Deque is empty.");
}
else if(capacity >= 4){
if(size() < capacity/2){
System.out.println("Capacity shrinking...");
int[] B = new int[capacity/2];
for(int i = 0; i < capacity/2; i++){
B[i] = A[i];
}
A = B;
}
}
int temp = A[rear - 1];
A[rear] = 0;
rear = (rear - 1) % capacity;
return temp;
}
} // end class
Here's the main class:
public class CircularExtendedArrayMain {
public static void main(String[] args) {
CircularExtendedArrayDeque q = new CircularExtendedArrayDeque();
q.insertFirst(112);
q.insertFirst(105);
q.printDeque();
System.out.println("last element is = " + q.getLast());
System.out.println("first element is = " + q.getFirst());
q.insertLast(5501);
q.printDeque();
q.insertLast(778);
q.insertLast(37);
q.printDeque();
System.out.println("first element is = " + q.getFirst());
System.out.println("last element is = " + q.getLast());
System.out.println("remove last = " + q.removeLast());
q.printDeque();
System.out.println("remove last = " + q.removeLast());
System.out.println("remove first = " + q.removeFirst());
q.printDeque();
System.out.println("remove first = " + q.removeFirst());
System.out.println("remove first = " + q.removeFirst());
// q is now empty.
int i, k;
for( i = 1; i <= 60; i ++ )
q.insertLast(i*i);
q.printDeque(); // 60 elements in q
for( i = 1; i <= 58; i++ )
k = q.removeFirst();
q.printDeque(); // two elements are left
}
}
Here's my output:
Front: 0 & Rear:1
Front: 0 & Rear:2
105 112
last element is = 112
first element is = 105
Front: 0 & Rear:3
msg...size=3
105 112 5501
Front: 0 & Rear:4
msg...size=4
Front: 0 & Rear:5
msg...size=5
105 112 5501 778 37
first element is = 105
last element is = 37
remove last = 37
105 112 5501 778
remove last = 778
remove first = 105
112 5501
remove first = 112
remove first = 5501
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at CircularExtendedArrayDeque.insertLast(CircularExtendedArrayDeque.java:161)
at CircularExtendedArrayMain.main(CircularExtendedArrayMain.java:34)
public void insertLast(int e) {
if(size() == capacity - 1) {
capacity= capacity*2;
}
int[] B = new int[capacity];
for(int i = 0; i < size(); i++) {
B[i] = A[i];
}
A = B;
A[rear] = e;
rear = (rear + 1) % capacity;
}
This is my insertLast(). Guess this works. Good luck with cse2011.. !!

Segment tree java implementation [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 6 years ago.
Improve this question
Do you know a good implementation of a (binary) segment tree in Java?
public class SegmentTree {
public static class STNode {
int leftIndex;
int rightIndex;
int sum;
STNode leftNode;
STNode rightNode;
}
static STNode constructSegmentTree(int[] A, int l, int r) {
if (l == r) {
STNode node = new STNode();
node.leftIndex = l;
node.rightIndex = r;
node.sum = A[l];
return node;
}
int mid = (l + r) / 2;
STNode leftNode = constructSegmentTree(A, l, mid);
STNode rightNode = constructSegmentTree(A, mid+1, r);
STNode root = new STNode();
root.leftIndex = leftNode.leftIndex;
root.rightIndex = rightNode.rightIndex;
root.sum = leftNode.sum + rightNode.sum;
root.leftNode = leftNode;
root.rightNode = rightNode;
return root;
}
static int getSum(STNode root, int l, int r) {
if (root.leftIndex >= l && root.rightIndex <= r) {
return root.sum;
}
if (root.rightIndex < l || root.leftIndex > r) {
return 0;
}
return getSum(root.leftNode, l, r) + getSum(root.rightNode, l, r);
}
/**
*
* #param root
* #param index index of number to be updated in original array
* #param newValue
* #return difference between new and old values
*/
static int updateValueAtIndex(STNode root, int index, int newValue) {
int diff = 0;
if(root.leftIndex==root.rightIndex && index == root.leftIndex) {
// We actually reached to the leaf node to be updated
diff = newValue-root.sum;
root.sum=newValue;
return diff;
}
int mid = (root.leftIndex + root.rightIndex) / 2;
if (index <= mid) {
diff= updateValueAtIndex(root.leftNode, index, newValue);
} else {
diff= updateValueAtIndex(root.rightNode, index, newValue);
}
root.sum+=diff;
return diff;
}
}
This has been implemented within the open source Layout Management SW Package project
Here is a link to the sub package
You might find the code useful. I have neither verified it nor run it and I cannot find the license the code is provided under from a quick search of the code and website so Caveat Emptor.
You may be able to contact the authors but the last activity appears to have been August 2008.
Here it is:
import java.util.Scanner;
public class MinimumSegmentTree {
static Scanner in = new Scanner(System.in);
public static void main(String[] args) {
final int n = in.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = in.nextInt();
}
int sizeOfSegmentTree = (int) Math.pow(2, Math.ceil(Math.log10(n) / Math.log10(2)));
sizeOfSegmentTree = 2*sizeOfSegmentTree-1;
// System.out.println(sizeOfSegmentTree);
int[] segmentTree = new int[sizeOfSegmentTree];
formSegmentTree(a, segmentTree, 0, n-1, 0);
// for(int i=0; i<sizeOfSegmentTree; i++){
// System.out.print(segmentTree[i]+" ");
// }
// System.out.println();
final int q = in.nextInt();
for (int i = 0; i < q; i++) {
int s, e;
s = in.nextInt();
e = in.nextInt();
int minOverRange = getMinimumOverRange(segmentTree, s, e, 0, n-1, 0);
System.out.println(minOverRange);
}
}
private static int getMinimumOverRange(int[] segmentTree, int qs, int qe, int s, int e, int pos) {
if (qs <= s && qe >= e) {
return segmentTree[pos];
}
if (qs > e || s > qe) {
return 10000000;
}
int mid = (s + e) / 2;
return Math.min(getMinimumOverRange(segmentTree, qs, qe, s, mid, 2 * pos + 1),
getMinimumOverRange(segmentTree, qs, qe, mid+1, e, 2 * pos + 2));
}
private static void formSegmentTree(int[] a, int[] segmentTree, int s, int e, int pos) {
if (e - s == 0) {
segmentTree[pos] = a[s];
return;
}
int mid = (s + e) / 2;
formSegmentTree(a, segmentTree, s, mid, 2 * pos + 1);
formSegmentTree(a, segmentTree, mid+1, e, 2 * pos + 2);
segmentTree[pos] = Math.min(segmentTree[2 * pos + 1], segmentTree[2 * pos + 2]);
}
}
Algo and unit tests:
public class NumArrayTest {
#Test
public void testUpdateSumRange_WithEmpty() throws Exception {
NumArray numArray = new NumArray(new int[]{});
assertEquals(0, numArray.sumRange(0, 0));
}
#Test
public void testUpdateSumRange_WithSingleton() throws Exception {
NumArray numArray = new NumArray(new int[]{1});
assertEquals(1, numArray.sumRange(0, 0));
numArray.update(0, 2);
assertEquals(2, numArray.sumRange(0, 0));
}
#Test
public void testUpdateSumRange_WithPairElements() throws Exception {
NumArray numArray = new NumArray(new int[]{1,2,3,4,5,6});
assertEquals(12, numArray.sumRange(2, 4));
numArray.update(3, 2);
assertEquals(10, numArray.sumRange(2, 4));
}
#Test
public void testUpdateSumRange_WithInPairElements() throws Exception {
NumArray numArray = new NumArray(new int[]{1,2,3,4,5,6,7});
assertEquals(12, numArray.sumRange(2, 4));
numArray.update(3, 2);
assertEquals(10, numArray.sumRange(2, 4));
}
}
public class NumArray {
private final Node root;
private static class Node {
private final int begin;
private final int end;
private final Node left;
private final Node right;
private int sum;
public Node(int begin, int end, int sum, Node left, Node right) {
this.begin = begin;
this.end = end;
this.sum = sum;
this.left = left;
this.right = right;
}
public boolean isSingle() {
return begin == end;
}
public boolean contains(int i) {
return i >= begin && i <= end;
}
public boolean inside(int i, int j) {
return i <= begin && j >= end;
}
public boolean outside(int i, int j) {
return i > end || j < begin;
}
public void setSum(int sum) {
this.sum = sum;
}
}
public NumArray(int[] nums) {
if (nums.length == 0) {
root = null;
} else {
root = buildNode(nums, 0, nums.length - 1);
}
}
private Node buildNode(int[] nums, int begin, int end) {
if (begin == end) {
return new Node(begin, end, nums[begin], null, null);
} else {
int mid = (begin + end) / 2 + 1;
Node left = buildNode(nums, begin, mid - 1);
Node right = buildNode(nums, mid, end);
return new Node(begin, end, left.sum + right.sum, left, right);
}
}
public void update(int i, int val) {
if (root == null) {
return;
}
if (!root.contains(i)) {
throw new IllegalArgumentException("i not in range");
}
update(root, i, val);
}
private int update(Node node, int i, int val) {
if (node.isSingle()) {
node.setSum(val);
} else {
Node nodeToUpdate = node.left.contains(i) ? node.left : node.right;
int withoutNode = node.sum - nodeToUpdate.sum;
node.setSum(withoutNode + update(nodeToUpdate, i, val));
}
return node.sum;
}
public int sumRange(int i, int j) {
if (root == null) {
return 0;
}
return sumRange(root, i, j);
}
private int sumRange(Node node, int i, int j) {
if (node.outside(i, j)) {
return 0;
} else if (node.inside(i, j)) {
return node.sum;
} else {
return sumRange(node.left, i, j) + sumRange(node.right, i, j);
}
}
}

Categories