I am learning java right now.
I have a class.
public static final int INIT_CAPACITY = 8; // 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 ArrayDeque( )
{
A = new int[ INIT_CAPACITY ];
capacity = INIT_CAPACITY;
front = rear = 0;
}
public int size( )
{
int countSize = 0;
for(int i = 0; i < capacity; i++)
{
if(A[i] != front && A[i] != rear)
{
countSize++;
}
}
// COMPLETE THIS METHOD
// Hint: size can be computed from capacity, front and rear.
return count; // replace this line with your code
}
I am trying to finish the method size. Does this make sense? Also, are there any good tips to check if I am on the right track?
My question might be too naive, my apology if it is. I just don't have lots of knowledge of programming.
Thank you
return count;
what is count? Do you mean countSize?
In either case your size method runs in O(N), if you had a million elements, you'd have to traverse the array a million times just to get the size. That isn't a good idea.
Instead, use the capacity private instance variable to denote the current size, like this:
public int size() {
return capacity;
}
and whenever you add an element, presumably in add(int x), increment capacity like: capacity++;
and whenever you delete an element, presumably in a remove(int x) or removeFirst()/removeLast(), decrement capacity like: capacity--;
and finally start capacity at 0 like: capacity = 0; inside your constructor, ArrayDeque().
Related
I want to shift the elements in the array in a queue style.
I did this code:
public class Queue {
private int[] elements;
private int size;
public static final int DefCap = 8;
public Queue() {
this(DefCap);
}
public Queue(int capacity) {
elements = new int[capacity];
}
public int[] enqueue(int v) {
if (size >= elements.length) {
int[] a = new int[elements.length * 2];
System.arraycopy(elements, 0, a, 0, elements.length);
elements = a;
}
elements[size++] = v;
return elements;
}
public int dequeue() {
return elements[--size];
}
public boolean empty() {
return size == 0;
}
public int getSize() {
return size;
}
}
How can I shift the numbers in the array where the next number added pushes the last one?
because all it does now is removes the last one added (Stacking).
First, remember that it doesn't matter at all how you add or retrieve the elements as long as it appears that the operation reflects that of a queue (i.e. FIFO). The internals of your implementation are of no concern to the user(s). The easiest method (imo) is to add them normally to the end and "remove" them from the beginning.
When you add the new element, do it like you are already doing it.
When you remove the first element, do it virtually by using an index.
int nextIdx = 0; // initialize start of queue
...
...
public int next() {
if (nextIdx < elements.length) {
return elements[nextIdx--];
}
// indicate an error by throwing an exception
}
At some point you are going to want to reclaim the "non-existent" elements at the beginning of the queue and then reset nextIdx. You can do this when you need to resize the array. You can use System.arraycopy and make use of both the value of nextIdx and the new desired new size to resize the array and copy the remaining elements.
Note: In your enqueue method I'm not certain why you want to return the entire element array when you add an element. I would expect something like returning the element just added, a boolean indicating success, or not return anything.
I am creating a class that has an array, and I want to implement methods add, remove, and replace.
But I don't want to use any built-in internals.
public class MySet {
public int set[];
private int size = 0;
public MySet(int size) {
this.set = new int[size];
}
public boolean add(int item) {
for (int i = 0; i < this.size(); i++) {
if (this.set[i] != 0) {
// add to array
}
}
this.size++;
return true;
}
public int size()
{
return this.size;
}
}
When you initialize an array with a fixed size in Java, each item is equal to 0. The part with if this.set[i] != 0 is where I am stuck to add an item.
Should I use a while loop with pointers? Such as:
public boolean add(int item) {
int index = 0;
while (index <= this.size()) {
if (this.set[index] != 0 || index <= ) {
// increase pointer
index++;
}
this.set[index] = item;
}
But if I have an array such as [7, 2, 0 , 1] in the list, it won't get the last item in the loop, which I need.
So, how is this usually done?
You should keep the current index for the size of populated elements which looks like you do. When you add the set[size]= item and increment size. Once size hits the preallocated size of your array you need to create a new array with increased size (can pick double the size for example) and copy old array to the new one.
I have a Point object that just has an x and y, and I have a Heap data structure that looks like so:
class MaxHeap{
public Point[] heap;
public int size;
public int maxsize;
public MaxHeap(int maxsize){
this.maxsize = maxsize;
this.size = 0;
heap = new Point[this.maxsize+1];
heap[0] = new Point(-1,-1); //Heap is empty
}
public int parent(int pos){
return pos /2;
}
public int leftChild(int pos){
return (2 * pos);
}
public int rightChild(int pos){
return (2 * pos) +1;
}
public boolean isLeaf(int pos){
if (pos >= (size / 2) && pos <= size){
return true;
}
return false;
}
public void swap (int fpos, int spos){
Point tmp;
tmp = heap[fpos];
heap[fpos] = heap[spos];
heap[spos] = tmp;
}
public void maxHeapify(int pos){
if (!isLeaf(pos)){
if (heap[pos].getY() < heap[leftChild(pos)].getY() || heap[pos].getY() < heap[rightChild(pos)].getY()){
swap(pos, leftChild(pos));
maxHeapify(leftChild(pos));
}
else{
swap(pos, rightChild(pos));
maxHeapify(rightChild(pos));
}
}
}
public void insert (Point p){
heap[++size] = p;
int current = size;
while (heap[current].getY() > heap[parent(current)].getY()){
swap(current, parent(current));
current = parent(current);
}
}
I am trying to implement a way to remove any Point from the Heap, instead of the traditional remove where it just removes the top. I'm not entirely sure how to go about doing this. I was thinking I could store the index of the Point in the heap inside of the Point. I'm not sure if this would help or not.
Just is case, are you aware that there is standard heap implementation in Java called PriorityQueue? You can use it as the reference of how removeAt(int i) is implemented.
Back to your question.
In order to remove intermediate element from the queue, you need to replace it with the last element of the queue (shrinking the queue by one element) and try to "heapify" this element down. If element is still in place (both children were bigger than the element) you need to "heapify" it up.
Regarding second part of your question. I'd not recommend storing queue indices inside Point class and hence making points queue-aware. The better way is to maintain Map from point to its index inside the queue (this map can be represented by IdentityHashMap[Point, Integer]). Just don't forget to make appropriate changes in this map when you are making changes in the queue, such as inserting, removing elements, swapping them and so on.
this is an anwser :
public void removeSpecificElement(int i) {
heap[i] = heap[size];
size--;
while (getParent(i) < heap[i] && i > 1 ) {
swapElements(heap[i], getParent(i));
i = getParent(i);
}
heapifyUp(i);
}
I am using array based MinHeap in java. I am trying to create a custom method which can remove any element not only root from the heap but couldn't. Below is MinHeap code-
public class MinHeap {
/** Fixed-size array based heap representation */
private int[] h;
/** Number of nodes in the heap (h) */
private int n = 0;
/** Constructs a heap of specified size */
public MinHeap(final int size) {
h = new int[size];
}
/** Returns (without removing) the smallest (min) element from the heap. */
public int peek() {
if (isEmpty()) {
throw new RuntimeException("Heap is empty!");
}
return h[0];
}
/** Removes and returns the smallest (min) element from the heap. */
public int poll() {
if (isEmpty()) {
throw new RuntimeException("Heap is empty!");
}
final int min = h[0];
h[0] = h[n - 1];
if (--n > 0)
siftDown(0);
return min;
}
/** Checks if the heap is empty. */
public boolean isEmpty() {
return n == 0;
}
/** Adds a new element to the heap and sifts up/down accordingly. */
public void add(final int value) {
if (n == h.length) {
throw new RuntimeException("Heap is full!");
}
h[n] = value;
siftUp(n);
n++;
}
/**
* Sift up to make sure the heap property is not broken. This method is used
* when a new element is added to the heap and we need to make sure that it
* is at the right spot.
*/
private void siftUp(final int index) {
if (index > 0) {
final int parent = (index - 1) / 2;
if (h[parent] > h[index]) {
swap(parent, index);
siftUp(parent);
}
}
}
/**
* Sift down to make sure that the heap property is not broken This method
* is used when removing the min element, and we need to make sure that the
* replacing element is at the right spot.
*/
private void siftDown(int index) {
final int leftChild = 2 * index + 1;
final int rightChild = 2 * index + 2;
// Check if the children are outside the h bounds.
if (rightChild >= n && leftChild >= n)
return;
// Determine the smallest child out of the left and right children.
final int smallestChild = h[rightChild] > h[leftChild] ? leftChild
: rightChild;
if (h[index] > h[smallestChild]) {
swap(smallestChild, index);
siftDown(smallestChild);
}
}
/** Helper method for swapping h elements */
private void swap(int a, int b) {
int temp = h[a];
h[a] = h[b];
h[b] = temp;
}
/** Returns the size of heap. */
public int size() {
return n;
}
}
How can i design a method to remove any element from this MinHeap?
If you know the index of the element to be removed,
private void removeAt(int where) {
// This should never happen, you should ensure to call it only with valid indices
if (n == 0) throw new IllegalArgumentException("Trying to delete from empty heap");
if (where >= n) throw new IllegalArgumentException("Informative error message");
// Now for the working cases
if (where == n-1) {
// removing the final leaf, trivial
--n;
return;
}
// other nodes
// place last leaf into place where deletion occurs
h[where] = h[n-1];
// take note that we have now one element less
--n;
// the new node here can be smaller than the previous,
// so it might be smaller than the parent, therefore sift up
// if that is the case
if (where > 0 && h[where] > h[(where-1)/2]) {
siftUp(where);
} else if (where < n/2) {
// Now, if where has a child, the new value could be larger
// than that of the child, therefore sift down
siftDown(where);
}
}
The exposed function to remove a specified value (if present) would be
public void remove(int value) {
for(int i = 0; i < n; ++i) {
if (h[i] == value) {
removeAt(i);
// assumes that only one value should be removed,
// even if duplicates are in the heap, otherwise
// replace the break with --i to continue removing
break;
}
}
}
Summarising, we can remove a node at a given position by replacing the value with the value of the last leaf (in the cases where the removal is not trivial), and then sifting up or down from the deletion position. (Only one or none sift needs to be done, depending on a comparison with the parent and/or children, if present.)
That works because the heap invariant is satisfied for the parts of the tree above and below the deletion position, so if the new value placed there by the swap is smaller than the parent, sifting up will place it in its proper position above the deletion position. All elements moved are smaller than any element in the children, so the heap invariant is maintained for the part below (and including) the deletion position.
If the new value is larger than one of the direct children, it's basically a removal of the root from the sub-heap topped at the deletion position, so the siftDown restores the heap invariant.
The fix for the mentioned flaw in the siftDown method is to set smallestChild to leftChild if rightChild >= n:
final int smallestChild = (rightChild >= n || h[rightChild] > h[leftChild]) ? leftChild
: rightChild;
// Queue.java
// demonstrates queue
// to run this program: C>java QueueApp
class Queue
{
private int maxSize;
private long[] queArray;
private int front;
private int rear;
private int nItems;
public Queue(int s) // constructor
{
maxSize = s;
queArray = new long[maxSize];
front = 0;
rear = -1;
nItems = 0;
}
public void insert(long j)
{
if(rear == maxSize-1)
rear = -1;
queArray[++rear] = j;
nItems++;
}
public long remove()
{
long temp = queArray[front++];
if(front == maxSize)
front = 0;
nItems--;
return temp;
}
public long peekFront()
{
return queArray[front];
}
public boolean isEmpty() // true if queue is empty
{
return (nItems==0);
}
public boolean isFull() // true if queue is full
{
return (nItems==maxSize);
}
public int size() // number of items in queue
{
return nItems;
}
public void display()
{ int startFront = front;
for (int j = front ;j <nItems; j++ )
{
System.out.println(queArray[j]);
if (j == nItems-1 )
{ j=0;
System.out.println(queArray[j]);
}
if (j==startFront-1)
return;
}
}
}
class QueueApp
{
public static void main(String[] args)
{
Queue theQueue = new Queue(5); // queue holds 5 items
theQueue.insert(10); // insert 4 items
theQueue.insert(20);
theQueue.insert(30);
theQueue.insert(40);
theQueue.remove(); // remove 3 items
theQueue.remove(); // (10, 20, 30)
theQueue.remove();
theQueue.insert(50); // insert 4 more items
theQueue.insert(60); // (wraps around)
theQueue.insert(70);
theQueue.insert(80);
theQueue.display();
while( !theQueue.isEmpty() ) // remove and display
{ // all items
long n = theQueue.remove(); // (40, 50, 60, 70, 80)
System.out.print(n);
System.out.print(" ");
}
System.out.println("");
} // end main()
} // end class QueueApp
Okay, this is the basic, out of the book, queue code. I am attempting to create a display method that will show the queue in order, from front to back. (This is an assignment, i know this is not practical....) If i run the program as is, it will display the queue in order from front to rear(at least that is what i believe i did). The problem i am having is if i change the nItems, it ceases to work. For example if you add the line of code, theQueue.remove(); right above the call to the display, the method ceases to work, i know it is because the front is now = to 4, instead of 3,and it will not enter the for method which needs the front to be < nItems, 4<4 is not true so the for loop does not initiate.
Simply use something like:
public void display() {
for (int i = 0; i < nItems; i++) {
System.out.println(queArray[(front + i) % maxSize]);
}
}
In my opinion you're using too many variables which you don't need. You only need the Queue size and its item count.
public Queue(int s) {
size = s;
queArray = new long[s];
nItems = 0;
}
public void insert(long j) {
if(nItems < size) {
queArray[nItems] = j;
nItems++;
}
}
public long remove() {
if(nItems > 0) {
long temp = queArray[nItems];
nItems--;
return temp;
}
}
public void display() {
for(int j = 0; j < nItems; j++) {
System.out.println(queArray[j]);
}
}
So what's happening right now is that j is the position of the element in your array, which is different from the number of elements that you've printed so far.
You need to either use a different index to count how many elements you printed or check whether you're at the end by comparing j to rear.
When the queue is full (rear == maxSize - 1) and you do a insert, it will replace the first
item, so i think the line nItems++ should not be incremented when the queue is already full.
Edit: Avoid modulus operations when you don't need them, they consume a lot of cpu.
The backing store for your queue is :
private long[] queArray;
Why don't you instead use :
private List<Long> queArray
and let List worry about the resizing effort after add/remove operations. Your current queue implementation needs to know exactly how many elements are going into the queue on construction. That's pretty inconvenient for clients using this API.
You can instantiate the queArray as :
queArray = new ArrayList<Long>();
in your constructor. Once you really understand that code, you can then move onto worrying about the re-sizing logic yourself.