For this generic array I added method reverse() that has to reverse the array without using an additional array of elements and I am trying to perform the reverse “in situ” using only swap operations. But I may have gotten it wrong and if so how can it be reversed “in situ” using only swap operations?
import java.util.Collections;
class GenericArray<E> {
private E[] array;
private int size;
public GenericArray() {
array = (E[]) new Object[10];
size = 0;
}
public E get(int i) {
return array[i];
}
public void set(int i, E value) {
if (i < size)
array[i] = value;
}
public void add(E value) {
array[size++] = value;
}
public boolean isFull() {
return size == array.length;
}
public void remove(int i) {
for (int j = i; j < size; j++)
array[j] = array[j + 1];
size--;
}
public void insert(int i, E value) {
for (int j = size; j >= i; j--)
array[j + 1] = array[j];
array[i] = value;
size++;
}
public void display() {
for (int i = 0; i < size; i++)
System.out.print(array[i] + " ");
System.out.println();
}
public E reverse() {
Collections.reverse(array);
}
}
If you mean that you want to do it manually without using Collections.reverse (that code shouldn't even compile btw, reverse needs a List as parameter), just traverse the array from the beginning to the middle swapping elements at the opposite sides of the range:
public E[] reverse() {
for (int i = 0; i < size/2; i++){
E tmp=array[i];
array[i] = array[size - i - 1];
array[size - i - 1]=tmp;
}
return array; // If you really want to return it
}
More info on in situ algorithms on wikipedia.
Regarding an add implementation that ensures that there is enough space:
public void add(E value) {
int newsize=size+1;
if(newsize<size){
//The array is big enough, add the element
array[newsize]=value;
}else{
//The array is too small, create a new one with
//the old content but twice as bigger and add
//the new element
array=Arrays.copyOf(array,size*2);
array[newsize]=value;
}
size=newsize;
}
Collections.reverse() does reversal "in situ"; you just need to give it the array as a list:
Collections.reverse(Arrays.asList(array));
Related
In our midterm exam teacher asked us to do this question below:
Write a generic Queue class which uses an array(not a link list) as a memory storage. It should support generic type parameter and array resizing (both growing and shrinking), but it doesn't have to support iterators.Hints:Queue is a FIFO data structure ; the API for a queue contains enqueue, dequeue,size and isEmpty methods in addition to the constructor; you don't have to implement toString.
I tried to write this code and here's what I wrote. But I don't know how should I check this code. Is it correct or how can I check it?
public class Queue<T> {
public T[] array;
public int N;
public boolean isEmpty() {
return N == 0;
}
public int size() {
return N;
}
public void resize(int max) {
T[] temp = (T[]) new Object[max];
for (int i = 0; i < N; i++) {
temp[i] = array[i];
}
array = temp;
}
public void enqueue(T item) {
if (isEmpty()) {
array[0] = item;
N++;
} else if (N == array.length) {
resize(array.length * 2);
array[N] = item;
N++;
} else {
array[N] = item;
N++;
}
}
public T dequeue() {
T value = array[0];
for (int i = 1; i < N; i++) {
array[i - 1] = array[i];
}
array[--N] = null;
return value;
}
}
here is the code with my revisions. I preserved your general approach I just made some fixes.
Of course other optimizations are possible but I'll leave them to you ;)
import java.lang.reflect.Array;
public class Queue<T> {
//never expose directly as public internal variables of your classes. So they should be private
private final Class<T> clazz;
private T[] array;
private int n;
//these 2 variables define the expansion and reducing policy so that may be changed dynamically
private final float policyToExpand = 3.0f/4.0f;
private final float policyToReduce = 1.0f/4.0f;
//you didn't implement the constructor of your class that was required. This should do the work.
//Just mind that the 4 it's the initial capacity of the array.
public Queue(Class<T> clazz) {
this.clazz = clazz;
this.array = (T[]) Array.newInstance(clazz, 4);
this.n = 0;
}
public boolean isEmpty() {
return n == 0;
}
public int size() {
return n;
}
//cleaned a bit enqueue and dequeue method and extrapolating the logic for resize.
public void enqueue(T item) {
array[n] = item;
n++;
if(expansionIsNeeded()) performResizeExpanding();
}
public T dequeue() {
T value = array[0];
slideBackArray();
n--;
if(reduceIsNeeded()) performResizeReducing();
return value;
}
//logic for sliding back items when dequeueing
private void slideBackArray() {
for (int i = 1; i < n; i++) {
array[i - 1] = array[i];
}
array[n] = null;
}
//these 2 methods take care of triggering resize
private boolean expansionIsNeeded() {
float currentFilling = (float) n / array.length;
return currentFilling >= policyToExpand;
}
private boolean reduceIsNeeded() {
float currentFilling = (float) n / array.length;
return currentFilling <= policyToReduce;
}
//these 2 instead perform the actual resize
private void performResizeExpanding() {
T[] tempArray = (T[]) Array.newInstance(clazz, this.array.length*2);
System.arraycopy(this.array, 0, tempArray, 0, n);
this.array = tempArray;
}
private void performResizeReducing() {
T[] tempArray = (T[]) Array.newInstance(clazz, this.array.length/2);
System.arraycopy(this.array, 0, tempArray, 0, n);
this.array = tempArray;
}
}
Some issues:
The first enqueue call will already produce an Null Pointer Exception. A minimal test would have revealed this. Your array is not initialised and so access to array.length or array[0] or similar will trigger a NPE. You need to initialise the array upon construction.
array.length * 2 will not change the array size when it is 0, it is probably best to initialise your array with a size of at least 1, and never allow it to be come less.
Code that shrinks the array is lacking.
dequeue should not have to move every element every time you call it. Typically, an array-based queue keeps track of the start of the data and the end, so that the used part of the array does not necessarily have to start at index 0. Instead of an N member, define start and end members.
Here is a possible adjustment of your class:
public class Queue<T> {
private T[] array;
private int start, end; // Instead of N, so to gain efficiency in dequeue
Queue() {
array = (T[]) new Object[1]; // Initialise!
}
public boolean isEmpty() {
return start == end;
}
public int size() {
return (end + array.length - start) % array.length;
}
public void resize(int max) {
T[] temp = (T[]) new Object[max];
if (end > start) {
end -= start;
System.arraycopy(array, start, temp, 0, end);
start = 0;
end %= max;
} else {
System.arraycopy(array, 0, temp, 0, end);
int size = array.length - start;
System.arraycopy(array, start, temp, max - size, size);
start = max - size;
}
array = temp;
}
public void enqueue(T item) {
array[end] = item;
end = (end + 1) % array.length;
if (start == end) {
resize(array.length * 2);
}
}
public T dequeue() {
if (array.length > 1 && size() <= array.length / 2) {
resize(array.length / 2); // Shrink
}
T value = array[start];
array[start] = null;
start = (start + 1) % array.length;
return value;
}
}
I need to implement this algorithm creating a new ArrayList object at each recursive call.
My starting Array contains integers in this order"20, 40 ,10, 30 ,50 ,5" , after sorting it I have 5,5,5,5,5,5. I think that the problem is in the recursive call and in the last for cicle of the SelectionSort because removing the last for I notice that the the first element is sorted correctly.
import java.util.*;
public class SelectionSort {
//var
public ArrayList<Integer> arr ;
//constructor
public SelectionSort(ArrayList<Integer> arr){
this.arr = arr;
}
public ArrayList<Integer> getarraylist() {
return arr;
}
public void sort(){
//position of the last sorted element
int minimum =0;
if (arr.size() <=0 ) return;
for ( int j = 1; j < arr.size()-1; j++ ) {
if (arr.get(j) < arr.get(0) ) {
minimum = j;
//swap element 0 and minimum
int temp = arr.get(0);
arr.set(0, arr.get(minimum));
arr.set(minimum, temp);
}
}
//recursive call, new array without first element (already sorted)
ArrayList<Integer> arr2 = new ArrayList<>(arr.subList(1,arr.size()));
SelectionSort s2 = new SelectionSort(arr2);
s2.sort();
for(int i=0;i<s2.getarraylist().size();i++) {
arr.set(i, s2.getarraylist().get(i));
}
}
Driver class
public class Main {
public static void main(String[] args) {
ArrayList<Integer> arr = new ArrayList<Integer (Arrays.asList(20,40,10,30,50,5));
System.out.println("\n ARRAY ELEMENTS \n ");
for (int i: arr) {
System.out.println(i);
}
System.out.println("\n SORTED ELEMENTS \n ");
SelectionSort s = new SelectionSort(arr);
s.sort();
for (int i: s.getarraylist()) {
System.out.println(i);
}
}
}
You have actually two bugs in your algorithm that, together, lead to the observed output.
The first bug is within the for-loop that determines the minimal element:
for ( int j = 1; j < arr.size()-1; j++ ) { ...
You terminate one element too early, i.e. the last element is never considered. Thus, after the first iteration, the 5 is the last element in your ArrayList. In fact, it is the last element in every of your ArrayLists. The fix is to not subtract 1 in the for-condition:
for ( int j = 1; j < arr.size(); j++ ) { ...
The second bug is in your last for-loop where you copy the values from index i of s2 to index i of arr. You neglect the fact that s2 is one element shorter than arr. Thus, the only element not overriden is the last element. The fix is to get the i-th element from s2, but write it at the i + 1-th index of arr:
arr.set(i + 1, s2.getarraylist().get(i));
Now let us take look at how those two bugs lead to the observed output. Since
the last element in your ArrayList is never overridden and
the last element is always the same,
all elements have the same value (in your test case: 5).
Some remarks on your code:
the variable minimum is superfluous and can be replaced with j.
If you replace all occurences of ArrayList in SelectionSort with List, you can actually simplify the last part of your code to:
// remove the line declaring arr2, it is no longer needed
SelectionSort s2 = new SelectionSort(arr.subList(1, arr.size()));
s2.sort();
// last for-loop not needed anymore, method ends here
This is possible because ArrayList#subList(...) states that "The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa."
You should take a little bit more care wrt. indentation.
You have some minor inconsistencies in your coding style. For example, sometimes you write a blank after ( or before a ) or {, sometimes you do not. See what you like more and use it uniformly.
In Java, variable-, parameter- and methodnames should be written in camelCase (getarraylist() -> getArrayList())
With your last loop:
for(int i=0;i<s2.getarraylist().size();i++) {
arr.set(i, s2.getarraylist().get(i));
}
This overrides every element with the same number. (Why you got all 5's as your result) This is because you only iterate to the second to last element (arr.size()-1). Then you copy the elements in the line:
ArrayList<Integer> arr2 = new ArrayList<>(arr.subList(1,arr.size()));
Eventually you are only copying the last element over (5) and then copying this to the final ArrayList arr.
Also you create another SelectionSort object every time you call the sort method. This is not good.
Here is the code I wrote:
public void sort(List<Integer> list){
//position of the last ordered element
int minimum =0;
if (list.size() <=0 ) return;
for ( int j = 1; j < list.size(); j++ ) {
if (list.get(j) < list.get(0) ) {
minimum = j;
//swap element 0 and minimum
int temp = list.get(0);
list.set(0, list.get(minimum));
list.set(minimum, temp);
}
}
sort(list.subList(1,list.size()));
}
I changed it to accept an argument of List<Integer> (Because the subList() method returns a List) and then got rid of the last loop and where you created new objects.
Also youll have to change
s.sort();
to:
s.sort(s.getarraylist());
Output:
ARRAY ELEMENTS
20
40
10
30
50
5
SORTED ELEMENTS
5
10
20
30
40
50
Im not sure I understand the question, but I created a recursive (and iterative) selectionSort and InsertionSort just for fun, hope it helps.
public class Sorts {
public static void swap(Comparable[] a, int i, int j) {
Comparable temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void selectionSortItr(Comparable[] a, int n) {
for (int i = 0; i < n - 1; i++) {
int f = i;
for (int j = i + 1; j < n; j++) {
if (a[j].compareTo(a[f]) < 0)
f = j;
}
swap(a, i, f);
}
}
public static int select(Comparable[] a, int n, int j, int f) {
if (j >= n)
return f;
if (a[j].compareTo(a[f]) < 0)
f = j;
return select(a, n, j + 1, f);
}
public static void selectionSort(Comparable[] a, int n, int i) {
if (i < n - 1) {
swap(a, i, select(a, n, i + 1, i));
selectionSort(a, n, i + 1);
}
}
public static void insertionSortItr(Comparable[] a) {
for (int i = 1; i < a.length; i++) {
int j;
Comparable cur = a[i];
for (j = i; j > 0 && cur.compareTo(a[j - 1]) < 0; j--) {
a[j] = a[j - 1];
}
a[j] = cur;
}
}
public static void insertionSortInner(Comparable[] a, Comparable cur, int j) {
if (j > 0 && cur.compareTo(a[j - 1]) < 0) {
a[j] = a[j - 1];
insertionSortInner(a, cur, j - 1);
} else {
a[j] = cur;
}
}
public static void insertionSort(Comparable[] a, int i, int n) {
if (i < n) {
insertionSortInner(a, a[i], i);
insertionSort(a, i + 1, n);
}
}
public static void main(String[] args) {
Integer[] a = new Integer[10];
for (int i = 0; i < 10; i++)
a[i] = (int) (Math.random()*100);
selectionSort(a, 10, 0);
for (int i = 0; i < 10; i++)
System.out.println(a[i]);
}
}
I am working with implement arraylist. I want to write a method that takes the last element and inserts it at the front. So far I got it to take the last element and insert it in front, and shift everything over. But, I can't seem to be able to delete the last element that was inserted in front. for example: (1,2,5) to (5,1,2) but I got (5,1,2,5). I am missing something in my replaceArray() method, but I don't really know what. Thanks for the help.
Constructor for the class:
public KWArrayList() {
capacity = INITIAL_CAPACITY;
theData = (E[]) new Object[capacity];
}
public void replaceArray(int index, E anElement) {
for (int i = size; i > index; i--){
theData[i] = theData[i - 1];
}
theData[index] = anEntry;
size--;
for (int i = 0; i < theData.length; i++){
System.out.println(theData[i]);
}
}
I would use this simple way of rotating the array (I think the method should be called rotate instead of replaceAll, because it's actually rotation the array by one position).
Here's the method rotate():
#SuppressWarnings("unchecked")
public void rotate() {
Object[] temp = new Object[theData.length];
//copy each element, except the first, from theData into temp by shifting one position off to the right
for (int i = temp.length - 1; i > 0; i--) {
temp[i] = theData[i - 1];
}
//move the last element into the first position
temp[0] = theData[theData.length - 1];
//update theData
theData = (T[]) temp;
}
Complete testable example
public class MyArrayList<T> {
int INITIAL_CAPACITY = 10;
int capacity;
T[] theData;
#SuppressWarnings("unchecked")
public MyArrayList() {
capacity = INITIAL_CAPACITY;
theData = (T[]) new Object[capacity];
}
#SuppressWarnings("unchecked")
public MyArrayList(int capacity) {
this.capacity = capacity;
theData = (T[]) new Object[this.capacity];
}
#SuppressWarnings("unchecked")
public void rotate() {
Object[] temp = new Object[theData.length];
//copy each element, except the first, from theData into temp by shifting one position off to the right
// to the right
for (int i = temp.length - 1; i > 0; i--) {
temp[i] = theData[i - 1];
}
// move the last element into the first position
temp[0] = theData[theData.length - 1];
// update theData
theData = (T[]) temp;
}
/**
* For testing purposes only. It doesn't handle out of bounds values of
* index.
*/
private void insert(T t, int index) {
theData[index] = t;
}
public void print() {
for (T t : theData) {
System.out.print(t + ", ");
}
System.out.println();
}
#SafeVarargs
public static <E> MyArrayList<E> of(E... elements) {
MyArrayList<E> m = new MyArrayList<>(elements.length);
for (int i = 0; i < elements.length; i++) {
m.insert(elements[i], i);
}
return m;
}
}
Test the rotate() method:
public class TestMyArrayList {
public static void main(String[] args) {
MyArrayList<Integer> m = MyArrayList.of(1, 2, 3, 4, 5);
m.print();
m.rotate();
m.print();
}
}
It will print out:
1, 2, 3, 4, 5,
5, 1, 2, 3, 4,
import java.util.Arrays;
public class KWArrayList <E>{
private E[] data; /* your list */
private int nbElt = 0; /* nb of element in your list */
/* no need to store the capacity since data.length give it */
KWArrayList(int capacity){
data = (E[]) new Object[capacity]; /* create */
}
private void resize() {
E[] tmp = (E[]) new Object[2 * data.length]; /* if the number of element >= capacity you double the capacity and copy old elt */
data = Arrays.copyOf(data, 2 * data.length);
}
public void add(E elt) {
if(nbElt >= data.length) {
resize();
}
data[nbElt++] = elt; /* add an elt */
}
public void add(E ... elt) { /* add multiple elt */
for(E e : elt) {
add(e);
}
}
public E removeLast() { /* remove the last elt and return it */
if(nbElt == 0) {
throw new IllegalStateException("nothing to remove");
}
return data[--nbElt];
}
public void removeLastAndInsertFront() {
data[0] = removeLast();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
if(nbElt == 0) {
return sb.append("]").toString();
}
for(int i = 0; i < nbElt; i++) {
sb.append(data[i]).append(", ");
}
sb.setLength(sb.length() - 2);
return sb.append("]").toString();
}
public static void main(String[] args) {
KWArrayList<Integer> data = new KWArrayList(1);
data.add(1, 2, 5);
System.out.println(data);
System.out.println("first delete");
data.removeLastAndInsertFront();
System.out.println(data);
System.out.println("second delete");
data.removeLastAndInsertFront();
System.out.println(data);
System.out.println("third delete");
data.removeLastAndInsertFront();
System.out.println(data);
}
}
public class MyArrayList extends ArrayList<Object>{
public void rotateRight(){
this.add(0, this.remove(this.size()-1));
}
public void rotateLeft(){
this.add(this.remove(0));
}
}
I've written this implementation. I'm assuming theData is of type int but you can change it to whatever. I also removed the parameters in the function since I don't use them.
First we copy the array into a temp variable.
Second, we save the first value in theData into another temp variable.
We then begin to shift starting from the beginning of theData until the second to last index.
Finally, we copy the first index saved from theData into first and assign it to the last index of the array.
Print
public void replaceArray() {
int [] temp = theData;
int last = theData[theData.length - 1];
for (int i = theData.length - 1; i > 0; i--){
temp[i] = theData[i - 1];
}
temp[0] = last;
for (int i = 0; i < theData.length; i++){
System.out.println(temp[i]);
}
}
use queue
if you waht your own, have a 2 ints of the positions of the begin and end of the list, while replaceArray just copy the element to position end; then end = (end+1) % capacity;begin = (begin +1) % capacity; (without removing - no need)
So, why won't this code work it is returning the original list always (I haven't put the return statement, but can someone determine why the logic behind my selection sort algorithm is not working). Any help would be gladly appreciated!
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class ArrayListDemo {
public static void main(String [] args) {
ArrayList <String> list = new ArrayList <String> (15);
list.add("Wilson");
list.add("Annans");
list.add("Manning");
list.add("Branday");
list.add("Smittens");
list.add(2, "Goddard Fey");
list.set((list.size()) - 1, "Brand Brandon");
list.add("Brand Boarders");
selectionSort(list);
}
static void selectionSort(ArrayList<String> a) {
int smallindex;
for(int i = 0; i < a.size(); i++) {
smallindex = i; // set first element as smallest
for(int j = i + 1; j < a.size(); j++) { // find smallest
if (a.get(j).compareTo(a.get(smallindex)) > 0) {
swap(a, i, j);
}
}
}
}
static void swap(ArrayList<String> a, int index1, int index2) {
String i_string = a.get(index1);
String j_string = a.get(index2);
String temp = i_string;
i_string = j_string;
j_string = temp;
}
}
Your swap(ArrayList<String> a, int index1, int index2) method creates local variables - i_string and j_string - and then swaps them. This has no impact on the contents of the input List a.
To change the value of the i'th element of the List a you must call a.set(i,newValue).
You can either implement the swap method yourself, or use the existing Collections.swap:
static void selectionSort(ArrayList<String> a) {
int smallindex;
for(int i = 0; i < a.size(); i++) {
smallindex = i; // set first element as smallest
for(int j = i + 1; j < a.size(); j++) { // find smallest
if (a.get(j).compareTo(a.get(smallindex)) > 0) {
Collections.swap(a, i, j);
}
}
}
}
If you wish to learn how to implement swap correctly, you can take a look at the JDK implementation:
public static void swap(List<?> list, int i, int j) {
final List l = list;
l.set(i, l.set(j, l.get(i)));
}
As you can see, this method sets the value returned by l.set(j, l.get(i)) to be the new i'th element of the List. l.set(j, l.get(i)) sets the value l.get(i) as the new j'th element of the List and returns the previous j'th element. Therefore the new i'th element of the List becomes the previous j'th element.
I am new to Java. I am trying to create a method for a custom PriorityQueue, that must uses an Array, which merges 2 PriorityQueues.
The problem is that while I have no errors in my code, the Java compiler in Eclipse calls java.lang.ArrayIndexOutOfBoundsException whenever I call that method in main.
About Merge method:
It's basically a method that takes the elements of 2 arrays and merges them into one array. Then it erases all the elements of the second array using the extractMax method:
So far my code is this:
//Custom Priority Queue
class PriorityQueue {
private int capacity;
private int queue[];
private int i;
public PriorityQueue() {
capacity = 100;
queue = new int[100];
i = 0;
}
public PriorityQueue(int size) {
capacity = size;
queue = new int[size];
i = 0;
}
protected void quickSort(int left, int right) {
int i = left, j = right;
int pivot = queue[(left + right) / 2];
while (i <= j) {
while (queue[i] > pivot)
i++;
while (queue[j] < pivot)
j--;
if (i <= j) {
int temp = queue[i];
queue[i] = queue[j];
queue[j] = temp;
i++;
j--;
}
}
if (left < j)
quickSort(left, j);
if (i < right)
quickSort(i, right);
}
public boolean insert(int number) {
if(i < capacity) {
queue[i] = number;
quickSort(0, i++);
return true;
}
return false;
}
public int extractMax() {
if(i == 0)
return -1;
else {
int tempQueue[] = new int[i-1];
int temp = queue[0];
for(int j=0; j<i-1; j++)
tempQueue[j] = queue[j+1];
queue = tempQueue;
i--;
return temp;
}
}
public boolean merge(PriorityQueue myPriorityQueue) {
if(i + myPriorityQueue.i < capacity) {
for(int j=0; j<myPriorityQueue.i; j++)
queue[i++] = myPriorityQueue.extractMax();
quickSort(0, i-1);
return true;
}
return false;
}
//Test Class
class PriorityQueueTest
{
public static void main(String args[])
{
PriorityQueue PQ1 = new PriorityQueue();
PriorityQueue PQ2 = new PriorityQueue();
PQ1.insert(1);
PQ1.insert(3);
PQ1.insert(5);
PQ2.insert(2);
PQ2.insert(4);
PQ2.insert(6);
PQ1.merge(PQ2);
}
}
So whenever i Run this in eclipse i get:
java.lang.ArrayIndexOutOfBoundsException: 2
at PriorityQueue.merge(PriorityQueue.java:89)
at PriorityQueueTest.main(PriorityQueueTest.java:22)
I tried to figure out why it does that, but it makes no sense.
In this example, the length of the 2 PriorityQueues doesn't exceed the capacity of PriorityQueue1. There must be something wrong when I try to access PriorityQueues elements.
Thanks, any help is appreciated.
The problem is here:
for(int j=0; j<myPriorityQueue.i; j++)
Queue[i++] = myPriorityQueue.extractMax();
QuickSort(0, i-1);
return true;
More specifically, since you are incrementing i with Queue[i++] - and that's your class variable i, not a local one - j will always be less than myPriorityQueue.i. Therefore, this loop will always run until j exceeds capacity and throw an ArrayIndexOutOfBounds exception when you try to access a Queue[] element larger than its length. In a loop like this you would usually use j to access the elements in the array inside the loop:
for(int j=0; j<myPriorityQueue.i; j++)
Queue[j] = myPriorityQueue.extractMax();
QuickSort(0, i-1);
This way will only access elements in Queue[] up to i, and j automatically increments at the end of each iteration of the loop.
Things are made more confusing by your choice to use i as one of your class variables to track how many things are in the queue, instead of something more descriptive like queued or stored, when single letters such as i and j are often used in loops; you actually did use i in your QuickSort loop, when your class also already has a variable i. Using un-descriptive names for variables outside of loop counters is bad practice and makes code more difficult to understand.