Trying to implement min-heap using logic of max-heap - java

I am trying to implement min-heap which includes methods like insert,delete and heap sort.I am using implementation of max-heap and trying to convert it to min-heap.But,i am having some minor issues.It's a very straight-forward method ,but i am missing something,which i am not able to get.
This is the Helper Max-heap implementation i am using:
public void trickleDown(int index)
{
int largerChild;
Node top = heapArray[index]; // save root
while(index < currentSize/2) // while node has at
{ // least one child,
int leftChild = 2*index+1;
int rightChild = leftChild+1;
// find larger child
if( rightChild < currentSize && // (rightChild exists?)
heapArray[leftChild].getKey() <
heapArray[rightChild].getKey() )
largerChild = rightChild;
else
largerChild = leftChild;
// top >= largerChild?
if(top.getKey() >= heapArray[largerChild].getKey())
break;
// shift child up
heapArray[index] = heapArray[largerChild];
index = largerChild; // go down
} // end while
heapArray[index] = top; // index <- root
} // end trickleDown()
/////// My Implementation
/** Removes the top element of the heap and returns it.
*
* Complexity: O(log n)
* #return Top (min/max) element of the heap.
* #throws IllegalStateException if the heap is empty.
*/
T remove() {
if (size == 0) {
throw new IllegalStateException();
}
Comparable root = data[0];
data[0] = data[size-1];
size--;
trickleDown(0);
return (T) root;
}
private void trickleDown(int i) {
int largerChild;
Comparable top = data[i]; // save root
while(i > size/2 ) // not on bottom row{
int leftChild = left(i);
int rightChild = right(i);
if(rightChild > size && data[left(i)].compareTo(data[right(i)]) < 0 )
largerChild = leftChild;
else
largerChild = rightChild;
if(data[i].compareTo(data[right(i)]) <= 0 )
break;
data[i] = data[largerChild];
i = largerChild;
}
data[i] = top;
}
///// Test File
void checkHeapOrder(MinHeap h) {
assertTrue(h != null);
for(int i = 1; i < h.size() / 2; ++i)
assertTrue("Heap order property is broken at element at position "
+ i,
h.data[i].compareTo(h.data[i*2]) < 0 &&
h.data[i].compareTo(h.data[i*2 + 1]) < 0);
}
#Test
public void testRemove() {
System.out.println("remove");
MinHeap h = new MinHeap(10);
boolean throws_exception = false;
try {
h.remove();
} catch (IllegalStateException e) {
throws_exception = true;
} catch (Throwable e) {
}
assertTrue("remove throws an exception when empty", throws_exception);
// Permutation of 0...9
int[] input = { 0, 5, 9, 2, 3, 1, 6, 8, 7, 4 };
for(int i : input)
h.insert(i);
assertTrue(h.isFull());
for(int i = 10; i > 0; --i) {
assertEquals(h.size(), i);
Integer x = (Integer)h.remove();
assertEquals(x, new Integer(10-i)); // Items are removed in correct order
checkHeapOrder(h);
}
testRemove Failed: expected<0> but was <1>
I am pretty sure that the code is simple and i have tried to change everything from max to min,but just missing on with something,which i am having a hard time figuring out.

Related

PriorityQueue implementation in Java with support for changePriority operation

I require an implementation of a Priority queue that allows decrease priority operation to allow for an efficient implementation for Prim's and Dijkstra's algorithm.
I've coded up a minHeap implementation using a HashMap to store the indices of elements in my heap.
The problem I'm working on requires the computation of the total weight of the minimum spanning tree obtained by using Prim's algorithm. While my implementation works for most test cases upto 200 nodes, I'm still getting the incorrect output for many larger test cases.
It is my understanding that such minheap based implementations of Priority queues using HashMaps are common, if I am wrong in my assumption, please provide the more suitable approach to this problem.
I've been trying to debug my code for 2 days now and it seems the only way to fix it would be to compare it with a correctly functioning implementation.
Therefore, can someone please share such a PriorityQueue implementation using HashMap in java.
Even though I've tried a lot of test cases and for all the ones I can trace on my own(upto 30 nodes) I've gotten correct answers so far, but if there are some specific boundary test cases that could help me identify the problem, that too will be great.
Here is my code, I understand debugging it will be time consuming for anyone else, but if there is something obvious I've missed and someone with more expertise can point out the mistake, that would be most appreciated.
import java.util.HashMap;
import java.util.NoSuchElementException;
public class Heap<Key extends Comparable<Key>> {
private Key[] heap;
private int maxN, n;
private HashMap<Key, Integer> map;
#SuppressWarnings("unchecked")
public Heap(int maxN) {
if(maxN < 0 ) throw new IllegalArgumentException();
this.maxN = maxN;
n = 0;
heap = (Key[]) new Comparable[maxN];
map = new HashMap<>(maxN);
}
boolean isEmpty() {
return n == 0;
}
boolean insert(Key e) {
if(n +1 > maxN) throw new IllegalArgumentException("maximum capacity reached " + maxN);
heap[n] = e;
map.put(e,n);
int i = n++;
while ( (i+1)/2 - 1 >= 0){
if ( e.compareTo(heap[(i+1)/2 - 1]) < 0 ) {
swap(i, (i+1)/2 - 1);
i = (i+1)/2 - 1;
}
else
break;
}
return true;
}
Key extractMin() {
if(n == 0) throw new NoSuchElementException("Priority queue underflow ");
Key min = heap[0];
swap(0, n-1);
map.remove(min);
n--;
int j = 0, s;
while(j <= (n/2)-1){
if(j == (n/2)-1 && n == (j+1)*2 )
s = (j+1)*2 - 1;
else
s = heap[(j+1)*2 - 1].compareTo(heap[(j+1)*2]) < 0 ? (j+1)*2 - 1 : (j+1)*2;
if(heap[j].compareTo(heap[s]) > 0 ){
swap(j, s);
j = s;
}
else break;
}
return min;
}
Key delete(Key e){
if(!map.containsKey(e)) throw new NoSuchElementException(e+"does not exist ");
int j = map.get(e), s;
Key del = e;
swap(j, n-1);
map.remove(e);
n--;
while( j <= n/2 - 1){
if(j == (n/2)-1 && n == (j+1)*2)
s = (j+1)*2 - 1;
else
s = heap[(j+1)*2 - 1].compareTo(heap[(j+1)*2]) < 0 ? (j+1)*2 - 1 : (j+1)*2;
if(heap[j].compareTo(heap[s]) > 0 ){
swap(j, s);
j = s;
}
else break;
}
return del;
}
boolean decreasePriority(Key e){
if(n == 0)
return insert(e);
if(map.containsKey(e))
delete(e);
return insert(e);
}
private void swap(int i, int j) {
Key t = heap[i];
heap[i] = heap[j];
heap[j] = t;
map.replace(heap[i], i);
map.replace(heap[j], j);
}
#Override
public String toString() {
String res = "[";
int i;
for (i = 0; i < n-1; i++){
res += heap[i] + ", ";
}
res += heap[i]+"]";
return res;
}
}
I think the problem is in your delete method. Your code does this:
swap item to be removed with the last item in the heap
reduce heap count
push the new item down the heap
You're making the assumption that heap[j] < heap[n-1]. That's not a valid assumption. Consider this heap:
1
6 2
7 8 3
If you delete the node with value 7, the value 3 replaces it:
1
6 2
3 8
You now have to move it up the tree to make a valid heap:
1
3 2
6 8
The key here is that if the item you're replacing is in a different subtree than the last item in the heap, it's possible that the replacement node will be smaller than the parent of the replaced node.
If you're removing an item from the middle of the heap, you swap the item with the last, then you have to check whether the replacement node moves up or down.
Something you should consider, though, is that to change an item's priority, you don't have to delete and re-add. All you have to do is change the priority and then adjust the item's position appropriately: move up or down to put it in its new position.
The delete method was incorrect, I was using the same procedure for arbitrary deletes as for extractMin, which did not take into account the fact that the element I replace the key to be deleted with could possibly go both up or down the heap. Using swim() and sink() methods I have rectified this error. Also to change priority deletion and insertion are not required, and a simple call to both swim and sink is sufficient.(only swim if only decreasing priority and only sink if only increasing).
import java.util.HashMap;
import java.util.NoSuchElementException;
public class Heap<Key extends Comparable<Key>> {
private Key[] heap;
private int maxN, n;
private HashMap<Key, Integer> map;
#SuppressWarnings("unchecked")
public Heap(int maxN) {
if(maxN < 0 ) throw new IllegalArgumentException();
this.maxN = maxN;
n = 0;
heap = (Key[]) new Comparable[maxN];
map = new HashMap<>(maxN);
}
boolean isEmpty() {
return n == 0;
}
boolean insert(Key e) {
if(n +1 > maxN) throw new IllegalArgumentException("maximum capacity reached " + maxN);
heap[n] = e;
map.put(e,n);
int i = n++;
swim(i);
return true;
}
Key extractMin() {
if(n == 0) throw new NoSuchElementException("Priority queue underflow ");
Key min = heap[0];
swap(0, n-1);
map.remove(min);
n--;
sink(0);
return min;
}
void delete(Key e){
if(!map.containsKey(e)) throw new NoSuchElementException(e+" does not exist ");
int j = map.get(e);
swap(j, n-1);
map.remove(e);
n--;
if(!swim(j))
sink(j);
}
void decreasePriority(Key e){
if(map.containsKey(e)){
int j = map.get(e);
swim(j);
}
else insert(e);
}
private void swap(int i, int j) {
Key t = heap[i];
heap[i] = heap[j];
heap[j] = t;
map.replace(heap[i], i);
map.replace(heap[j], j);
}
private boolean swim(int j){
boolean change = false;
int parent;
while( (parent = (j-1)/2 ) >= 0){
if(heap[j].compareTo(heap[parent]) < 0){
swap(j,parent);
j = parent;
change = true;
}
else break;
}
return change;
}
private void sink(int j){
while(j <= n/2 - 1){
int leftChild = j*2 + 1, rightChild = leftChild + 1, s;
if(rightChild >= n)
s = leftChild;
else
s = heap[leftChild].compareTo(heap[rightChild]) < 0 ? leftChild : rightChild;
if(heap[j].compareTo(heap[s]) > 0){
swap(j,s);
j = s;
}
else break;
}
}
#Override
public String toString() {
String res = "[";
int i;
for (i = 0; i < n-1; i++){
res += heap[i] + ", ";
}
res += heap[i]+"]";
return res;
}
}
Edit: Be careful with your class comparator.

Error on Binary Search & Merge Sort Functions (with IO & command line)

I am experiencing an error. Running this program requires referencing the compiled jar file in a command line to specify the targets that must be found in the input file.
The error that is happening is any target string specified in the command line (that is present in the input file) gets an output of " not found", when it should be outputting " found on line {lineNumber}".
I went through the entirety of the class and frankly, I'm completely lost as to where this error occurs.
Any help is appreciated.
Main Class:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Search {
public static void main(String[] args) throws FileNotFoundException {
Scanner in = null;
int index = 0;
String[] word = null;
int[] lineNumber = null;
// check number of command line arguments is at least 2
if (args.length < 2) {
System.out.println("Usage: Search <input file> <target1> [target2...]");
System.exit(1);
}
// initialize Scanner
in = new Scanner(new File(args[0]));
// matches the end of a file character
in.useDelimiter("\\Z");
// puts entire file into one string
String temp = in.next();
in.close();
// intialize arrays & plug elements in
word = temp.split("\n");
lineNumber = new int[word.length];
populate(lineNumber);
// sort String array
mergeSort(word, lineNumber, 0, word.length - 1);
// if multiple targets exist
if (args.length > 2) {
for (int i = 1; i < args.length; i++) {
index = binarySearch(word, 0, word.length - 1, args[i]);
if (index < 0) {
System.out.println(args[i] + " not found");
} else {
System.out.println(args[i] + " found on line " + lineNumber[index]);
}
}
// if only single target specified in command line
} else {
index = binarySearch(word, 0, word.length - 1, args[1]);
if (index < 0) {
System.out.println(args[1] + " not found");
} else {
System.out.println(args[1] + " found on line " + lineNumber[index]);
}
}
}
// recursively halves arrays then plugs into merge function
public static void mergeSort(String[] word, int[] lineNumber, int p, int r) {
int q;
if (p < r) {
// q is midpoint
q = (p + r) / 2;
// recursive stuff
mergeSort(word, lineNumber, p, q);
mergeSort(word, lineNumber, q + 1, r);
// merge arrays
merge(word, lineNumber, p, q, r);
}
}
// merges sorted String arrays into one large sorted String array
public static void merge(String[] word, int[] lineNumber, int p, int q, int r) {
// element ranges
int n1 = q - p + 1;
int n2 = r - q;
// half String arrays to be merged
String[] L = new String[n1];
String[] R = new String[n2];
// half int arrays to be merged
int[] iL = new int[n1];
int[] iR = new int[n2];
// array indexes (for looping)
int i, j, k;
// plugging specific elements into new array
for (i = 0; i < n1; i++) {
L[i] = word[p + i];
iL[i] = lineNumber[p + i];
}
// plugging specific elements into new array
for (j = 0; j < n2; j++) {
R[j] = word[q + j + 1];
iR[j] = lineNumber[q + j + 1];
}
// reset array indexes
i = 0;
j = 0;
// loop through entirety of elements
for (k = p; k <= r; k++) {
// if both arrays still have unmerged element(s)
if (i < n1 && j < n2) {
// if left array's element precedes right's element
// lexicographically
if (L[i].compareTo(R[j]) < 0) {
word[k] = L[i];
lineNumber[k] = iL[i];
i++;
} else { // if right's element precedes (or the words are equal)
word[k] = R[j];
lineNumber[k] = iR[j];
j++;
}
// if only left array has unmerged element(s)
} else if (i < n1) {
word[k] = L[i];
lineNumber[k] = iL[i];
i++;
// if only right array has unmerged element(s)
} else {
word[k] = R[j];
lineNumber[k] = iR[j];
j++;
}
}
}
// searches sorted String array and returns index of target (or -1 if not
// found)
public static int binarySearch(String[] word, int p, int r, String target) {
int q;
if (p > r) {
return -1;
} else {
q = (p + r) / 2;
if (target == word[q]) {
return q;
} else if (target.compareTo(word[q]) < 0) {
return binarySearch(word, p, q - 1, target);
} else {
return binarySearch(word, q + 1, r, target);
}
}
}
// helper method: plugs numbers (in order) into an int array
public static void populate(int[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = i + 1;
}
}
}
You need to change the below method. String should be compared with equals() method and use trim() method to avoid trailing spaces.
public static int binarySearch(String[] word, int p, int r, String target) {
int q;
if (p > r) {
return -1;
} else {
q = (p + r) / 2;
if (target.trim().equals(word[q].trim())) {
return q;
} else if (target.compareTo(word[q]) < 0) {
return binarySearch(word, p, q - 1, target);
} else {
return binarySearch(word, q + 1, r, target);
}
}
}

Sorted Vector - AddItem

I have written a sorted vector which works fully. However my Add method is very long and I feel like there is a lot of redundant code.
I have a binary search function written and I would like to use this in my Add method instead of doing comparisons in the Add function also.
Below is my code:
public class SortedVector
{
private int maxcap = 10, noOfItems = 0, grow = 10;
private String[] data = new String[maxcap];
// Default Constructor
public SortedVector()
{
}
public void SetGrowBy(int growby)
{
grow = growby;
}
public int GetCapacity()
{
return maxcap;
}
public int GetNoOfItems()
{
return noOfItems;
}
public String GetItemByIndex(int index)
{
if (index > noOfItems+1 || index < 0)
{
return null;
}
else
{
String item = data[index];
return item;
}
}
public int FindItem(String search)
{
int low=0;
int high = noOfItems - 1;
return binarySearch(search, low, high);
}
public int binarySearch(String search, int low, int high)
{
if(low>high)
return -1;
int mid = (low + high)/2;
if (data[mid] == search)
return mid;
else
if (data[mid].compareToIgnoreCase(search)<0)
return binarySearch(search, mid+1, high);
else
return binarySearch(search, low, mid-1);
}
public void AddItem(String value)
{
int thirdCounter = 0;
int fourthCounter = 0;
int place3= 0;
int place4 =0;
if(maxcap > noOfItems)
{
if(noOfItems == 0)
{
data[0] = value;
noOfItems++;
}
else
{
int firstCounter = noOfItems;
for (int i=0; i < firstCounter; i++)
{
String[]temp = new String[maxcap];
if(thirdCounter == 0)
{
if (data[i].compareToIgnoreCase(value)>0)
{
for (int j=0; j < noOfItems; j++)
{
temp[j+1] = data[j];
}
data=temp;
data[0] = value;
noOfItems++;
thirdCounter++;
}
else
{
if(data[i].compareToIgnoreCase(value)<0)
{
for (int j=0; j < noOfItems; j++)
{
if (data[j].compareToIgnoreCase(value)>0)
{
if(fourthCounter ==0)
{
temp[j+1] = data[j];
place3 = j;
fourthCounter++;
}
else
{
temp[j+1] = data[j];
}
}
else
{
temp[j]=data[j];
place4 = j;
}
}
if (place3 == 0)
{
if(place4 == 0)
{
data=temp;
data[1] = value;
noOfItems++;
firstCounter++;
}
else
{
data=temp;
data[place4+1] = value;
noOfItems++;
thirdCounter++;
}
}
else
{
data=temp;
data[place3] = value;
noOfItems++;
thirdCounter++;
}
}
}
}
}
}
}
else
{
int firstCounter = 0;
maxcap = grow +maxcap;
String[]temp3 = new String[maxcap];
for (int i=0; i < noOfItems; i++)
{
if(firstCounter == 0)
{
if (data[i].compareToIgnoreCase(value)>0)
{
for (int j=0; j < noOfItems; j++)
{
temp3[j+1] = data[j];
}
data=temp3;
data[0] = value;
noOfItems++;
firstCounter++;
}
else
{
int place1 = 0;
int place2 = 0;
int secondCounter = 0;
if(data[i].compareToIgnoreCase(value)<0)
{
for (int j=0; j < noOfItems; j++)
{
if (data[j].compareToIgnoreCase(value)>0)
{
if(j/2!=0 && secondCounter ==0)
{
temp3[j+1] = data[j];
place1 = j;
secondCounter++;
}
else
{
temp3[j+1] = data[j];
}
}
else
{
temp3[j]=data[j];
place2 = j;
}
}
if (place1 == 0)
{
if(place2 == 0)
{
data=temp3;
data[1] = value;
noOfItems++;
firstCounter++;
}
else
{
data=temp3;
data[place2+1] = value;
noOfItems++;
firstCounter++;
}
}
else
{
data=temp3;
data[place1] = value;
noOfItems++;
firstCounter++;
}
}
}
}
}
}
System.out.println("adding: "+value);
}
public void DeleteItem(int index)
{
if (index < noOfItems && index >= 0)
{
data[index] = null;
if (data[index+1] != null)
{
int j = index;
for(int i = (index+1); i<noOfItems; i++)
{
data[j] = data[i];
j++;
}
}
noOfItems--;
}
System.out.println("deleted: "+index);
}
public String toString()
{
return super.toString();
}
}
Any tips on how I could do that much appreciated.
Kind Regards,
Ben.
Implementing the add, (binaryAdd) is almost identical to how you implemented the binary search. The code will be 99% similar.
Let say you have the following data:
+--------------------------+
|10|20|30|40|50|60|70|80|90|
+--------------------------+
You want to add 35 into it and keep the data in ascending order.
The mid value is 50, and since 35 is < 50, we are interested in 10 to 50:
+--------------+
|10|20|30|40|50|
+--------------+
The mid value is 30, and since 35 is > 30, we are interested in 30 to 50:
+--------+
|30|40|50|
+--------+
The mid value is 40, and since 35 is < 40, we are interested in 30 to 40:
+-----+
|30|40|
+-----+
When you left with 2 elements, choose either left or the right for comparison:
if you choose left, 35 > 30, so 35 should be added after 30.
if you choose right, 35 < 40, so 35 should be before after 40.
The process is similar to binary search, but instead of returning the position of the target value, you return the position to insert the value.
Here it is
DEMO: https://repl.it/Eqak/0
public void AddItem(String value)
{
// Check if cursor at last
if(noOfItems + 1 == maxcap){
// Resize data
maxcap *= 2;
String[] newData = new String[maxcap];
System.arraycopy(data, 0, newData, 0, noOfItems);
data = newData;
}
// find the last element according to value
int idx = 0;
for(; idx<noOfItems; idx++){
if(data[idx].compareToIgnoreCase(value) >= 0) {
break;
}
}
// move elements if required
if(idx < noOfItems){
System.arraycopy(data, idx, data, idx+1, noOfItems-idx);
}
// set element on index
data[idx] = value;
noOfItems++;
System.out.println("adding: "+value);
}
The easiest way is make the binarySearch return the insertion position if the element is not found. Very much like Arrays.binarySearch does:
returns: index of the search key, if it is contained in the array; otherwise, (-(insertion point) - 1)
So, if the return of the ret=binarySearch is negative, you only need to take -ret-1 to get the insert position.
You can even take a look to the code, its open source anyway (i.e. not only it runs, but you can use it to learn from it)
(no, I won't copy/paste that piece of code; link-only answer - take it or leave it).

Heap Data-Structure Re-Heap Method

I'm working on my assignment, which is to read from a text file, store the first 10 words in a heap. Then continue to read from the text file and if the word is less than the root of the heap, to replace it and re-heap the entire heap. My code seems to be working for the most part however I am running into a few problems.
Some words even though they are less than the root are not being swapped
Duplicate words
I am supposed to end up with a heap containing the words abandoning abandons
abased
abash
abashed
abashes
abasing
abate
abatement
abbe
However I get the words, abashes
abashed abash
abased abandons abandoning bewilderedly
abandoning armful abandoning
Here is my code so far:
public static void readFile() {
BufferedReader reader;
String inputLine;
int counter = 0;
try {
reader = new BufferedReader(new FileReader(".\\src\\dictionary.txt"));
while((inputLine = reader.readLine()) != null) {
if(counter < 10) {
heap.insert(inputLine);
counter++;
}
if(inputLine.compareTo(heap.find(0)) < 0) {
heap.change(0, inputLine);
}
}
} catch (IOException e) {
System.out.println("Error: " + e);
}
}
public boolean insert(String value) {
if(currentSize == maxSize) { return false; }
Node newNode = new Node(value);
heap[currentSize] = newNode;
trickleUp(currentSize++);
return true;
}
public void trickleUp(int index) {
int parent = (index - 1) / 2;
Node bottom = heap[index];
while(index > 0 && heap[parent].getData().compareTo(bottom.getData()) < 0) {
heap[index] = heap[parent];
index = parent;
parent = (parent - 1) / 2;
}
heap[index] = bottom;
}
public void trickleDown(int index) {
int largerChild;
Node top = heap[index];
while(index < currentSize / 2) {
int leftChild = 2 * index + 1;
int rightChild = index + 1;
if(rightChild < currentSize && heap[leftChild].getData().compareTo(heap[rightChild].getData()) < 0) {
largerChild = rightChild;
} else {
largerChild = leftChild;
}
if(top.getData().compareTo(heap[largerChild].getData()) > 0) {
break;
}
heap[index] = heap[largerChild];
index = largerChild;
}
heap[index] = top;
}
public boolean change(int index, String newValue) {
if(index < 0 || index >= currentSize) { return false; }
String oldValue = heap[index].getData();
heap[index].setData(newValue);
if(oldValue.compareTo(newValue) < 0) {
trickleUp(index);
} else {
trickleDown(index);
}
return true;
}
You won't get binary tree if you use such indexing:
int leftChild = 2 * index + 1;
int rightChild = index + 1;
I think you meant to write this:
int leftChild = 2 * index + 1;
int rightChild = 2 * index + 2;
So the tree will look like this
0
/ \
1 2
/ \ / \
3 4 5 6
/ \
7 8 ... and so on
As for duplicate elements as far as I know heap can contain duplicates and does not support duplicate removal. For example this is a valid heap of numbers
10
/ \
9 8
/ \ / \
5 7 7 6

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.. !!

Categories