I have written my own priority_queue based on unsorted array, so adding new element works fast in O(1) but removing element with max priority(minimal value) works slow in O(N)
import java.util.*;
public class PriorityQueue<K extends Comparable> {
private int index;
private Comparable[] elements;
public Object[] getElements() {
return elements;
}
public PriorityQueue(int capacity) {
if (capacity < 0)
capacity = 10;
elements = new Comparable[capacity];
}
public PriorityQueue() {
this(10);
}
public boolean isEmpty() {
return index == 0;
}
public int size() {
return index;
}
private void resize() {
elements = Arrays.copyOf(elements, elements.length * 2);
}
public void add(K element) {
if (index == elements.length)
resize();
elements[index++] = element;
}
public Comparable remove() {
if (isEmpty())
throw new PriorityQueueIsEmptyException("Queue is empty!");
int priorityIndex = 0;
for (int i = 1; i < index; i++) {
if (elements[i].compareTo(elements[priorityIndex]) < 0)
priorityIndex = i;
}
Comparable result = elements[priorityIndex];
index--;
elements[priorityIndex] = elements[index];
return result;
}
public Comparable<K> poll() {
if (isEmpty())
return null;
return remove();
}
public Comparable element() {
if (isEmpty())
throw new PriorityQueueIsEmptyException("Queue is empty!");
int priorityIndex = 0;
for (int i = 1; i < index; i++) {
if (elements[i].compareTo(elements[priorityIndex]) < 0)
priorityIndex = i;
}
return elements[priorityIndex];
}
public Comparable peek() {
if (isEmpty())
return null;
return element();
}
public Iterator iterator() {
return new QueueIterator();
}
public void print() {
for (int i = 0; i < index; i++) {
System.out.print(elements[i] + " --> ");
}
System.out.println();
}
private class QueueIterator implements Iterator {
// we keep list of indexes of elements that have been taken allready by method next()
// we keep it in order not to check elements with such indexes when we are founding new min element
// sorry for my eng
private List<Integer> usedIndexes;
private Comparable next;
public QueueIterator() {
usedIndexes = new ArrayList<Integer>();
}
private Comparable min(Comparable[] elements, int from, int to, List<Integer> usedIndexes) {
// trick to assign min value
// we cannot start from the first element cause he might be minimal allready
int startIndex = from;
for (int i = from; i <= to; i++) {
if (!usedIndexes.contains(i)) {
startIndex = i;
break;
}
}
Comparable min = elements[startIndex];
int minIndex = startIndex;
for (int i = from; i <= to; i++) {
if (!usedIndexes.contains(i) && elements[i].compareTo(min) < 0) {
min = elements[i];
minIndex = i;
}
}
usedIndexes.add(minIndex);
return min;
}
#Override
public boolean hasNext() {
return usedIndexes.size() == index;
}
#Override
public Comparable next() {
if (isEmpty())
throw new NoSuchElementException();
next = min(elements, 0, index - 1, usedIndexes);
return next;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}
public class PriorityQueueIsEmptyException extends RuntimeException {
PriorityQueueIsEmptyException() {
}
PriorityQueueIsEmptyException(String message) {
super(message);
}
}
My questions are:
had I made iterator right?
it seems to me that its not good that method next(), which works in O(N * N), am I right?
is there any way to do iterator better?
Related
Basically it's a array list implementation and I need to time how long it takes to add elements to it, along with other features. I compiled it though and there's no output and I can't find the problem. I instantiate an array of objects in the class then defined a method add(E e) to add an element E using basic assignment. Then the ListDriver should populate the array using the add() method and print it, but again, no output.
public class MyArrayList<E> {
public Object array[];
public int size = 0;
private static final int INITIAL_CAPACITY = 100;
public MyArrayList() {
array = new Object[INITIAL_CAPACITY];
this.size = 0;
}
private boolean arrayFull() {
if (size == array.length)
return true;
else
return false;
}
private boolean remove(Object o) {
for (int i = 0; i < size; i++) {
if (array[i].getClass() == o.getClass()) {
remove(i);
return true;
}
}
return false;
}
private void resize(int i) {
if (i == 0) {
Object[] temp = new Object[array.length*2];
for (int j = 0; j < size; j++) {
temp[j] = array[j];
}
this.array = temp;
}
if (i == 1) {
Object[] temp = new Object[array.length/2];
for (int j = 0; j < size; j++) {
temp[j] = array[j];
}
this.array = temp;
}
}
public void add(E e) {
if (!arrayFull()) {
array[size] = e;
size++;
}
else if (arrayFull()) {
resize(0);
add(e);
}
}
public int size() {
return size;
}
private void clear() {
array = null;
}
private Object remove(int index) {
if (halfFull()) {
resize(1);
}
Object temp = array[index];
for (int i = index; i < size; i++) {
array[i] = array[i+1];
}
size--;
return temp;
}
private boolean halfFull() {
if (size < (array.length/4)) {
return true;
}
else return false;
}
public void add(int index, E element) {
if (!arrayFull()) {
for (int i = size-1 ; i >= index ; i--) {
array[i] = array[i+1];
}
array[index] = element;
size++;
}
else {
resize(0);
add(index, element);
}
}
public String toString() {
String list = new String();
for (int i = 0; i < size; i++) {
list += " " + array[i];
}
return list;
}
public static void main(String[] args) {
MyArrayList temp = new MyArrayList();
System.out.println(temp.size);
}
}
And the driver
public class ListTester {
public static void main(String[] args) {
int n = 100;
MyArrayList arrayList = new MyArrayList();
int[] array = new int[n];
for (int i = 0; i < array.length; i++) {
array[i] = (int)Math.random() *2*n +1;
}
long startTime = System.nanoTime();
for (int i = 0; i < arrayList.size(); i++) {
arrayList.add(array[i]);
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println(arrayList);
System.out.println(duration);
}
}
import java.util.Arrays;
import java.util.Iterator;
public class ArrayList<Type> implements Iterable<Type> {
Type[] arr = (Type[]) new Object[10];
int size = 0;
//change capacity
public void newCapacity(int i) {
if (i == 0) {
int newIncreasedCapacity = arr.length * 2;
arr = Arrays.copyOf(arr, newIncreasedCapacity);
} else if (i == 1) {
int newDecreasedCapacity = arr.length / 2;
arr = Arrays.copyOf(arr, newDecreasedCapacity);
}
}
// add an item
public void add(Type item) {
if (size == arr.length) {
newCapacity(0);
}
arr[size++] = item; //increases size after appending
}
//remove an item
public Type remove(int index) {
if (size <= arr.length / 4) {
newCapacity(1);
}
Type removedItem = (Type) arr[index];
for (int i = index; i < size - 1; i++) {
arr[i] = arr[i + 1];
}
size -= 1;
return removedItem;
}
public int size() {
int count = 0;
for (int i = 0; i < size; i++) {
count += 1;
}
return count;
}
#Override
public Iterator<Type> iterator() {
return new ArrayIterator(arr);
}
class ArrayIterator<Type> implements Iterator<Type> {
private Type[] arrayList;
public ArrayIterator(Type[] newArray) {
arrayList = newArray;
}
// check if next element not null
public boolean hasNext() {
return (arrayList[size + 1] != null);
}
// next element
public Type next() {
if (arrayList[size + 1] != null) {
return (arrayList[size + 1]);
} else {
return null;
}
}
}
// Main Method
public static void main(String[] args) {
ArrayList<Integer> new_arr = new ArrayList<>();
new_arr.add(5);
new_arr.add(7);
new_arr.add(9);
new_arr.remove(0);
System.out.println(new_arr.size());
for (int i : new_arr) {
System.out.println(new_arr.size());
System.out.println(i);
}
}
}
I implemented the code for a custom ArrayList and also implemented an iterator for my custom data type, but I am facing an issue.
So when i run the for each loop in the main method, the loop does not run and thus nothing is printed on the console.I have checked the array which is being used for the for-each loop is not empty.Please help!
I think that you should fix your Iterator to something like
class ArrayIterator<Type> implements Iterator<Type> {
private Type[] arrayList;
private int position;
public ArrayIterator(Type[] newArray) {
arrayList = newArray;
position = 0;
}
// check if next element not null
public boolean hasNext() {
return (position != size);
}
// next element
public Type next() {
if (arrayList[position] != null) {
return (arrayList[position++]);
} else {
return null;
}
}
}
You are using the position of the size of the array to calculate the next() and hasNext(), the hasNext() is always returning null.
I need to write a method that when given a number it adds the number to all other elements in the array. For example if the value is 3 and you add 5 the new value will be 8. I tried this method but i got an error that I'm seeing for the first time. I'm talking about the last method the addValue method.
Code:
class IntegerList {
private LinkedList<Integer> integers;
public IntegerList() {
this.integers = new LinkedList<>();
}
public IntegerList(Integer... numbers) {
integers = new LinkedList<Integer>(Arrays.asList(numbers));
}
public boolean validateIndex(int index) {
if(index < 0 || index > integers.size()) {
throw new ArrayIndexOutOfBoundsException();
}
return true;
}
public void add(int el, int idx) {
int size = integers.size();
if(idx < integers.size()) {
integers.add(idx, el);
} else if(idx > integers.size()) {
size = idx;
el = 0;
}
}
public int remove(int idx) {
return integers.remove(idx);
}
public void set(int el, int idx) {
integers.add(idx, el);
}
public int get(int idx) {
return integers.get(idx);
}
public int size() {
return integers.size();
}
public int count(int el) {
int count = 0;
for(int i: integers) {
if(el == i) {
count++;
}
}
return count;
}
public void removeDuplicates() {
for(int i = 0; i < integers.size(); i++) {
Integer integer = integers.get(i);
for(int j = 0; j < i; j++) {
if(integer.equals(integers.get(i))) {
integers.remove(j);
i--;
break;
}
}
}
}
private int validateCount(int count) {
if(count > integers.size()) {
return integers.size();
}
return count;
}
public int sumFirst(int k) {
k = validateCount(k);
return integers.stream().limit(k).mapToInt(Integer::valueOf).sum();
}
public int sumLast(int k) {
k = validateCount(k);
return integers.stream().skip(integers.size() - k).mapToInt(Integer::valueOf).sum();
}
public void shiftRight(int index, int count) {
validateIndex(index);
int shiftIndex = (index + count) % integers.size();
Integer element = integers.remove(index);
integers.add(shiftIndex, element);
}
public void shiftLeft(int index, int count) {
validateIndex(index);
int shiftIndex = (index - count) % integers.size();
if(shiftIndex < 0) {
shiftIndex = integers.size() + shiftIndex;
}
Integer element = integers.remove(index);
integers.add(shiftIndex, element);
}
public IntegerList addValue(int value) {
return new IntegerList(
integers.stream()
.map(objectInteger -> new Integer(objectInteger + value))
.collect(Collectors.toCollection(LinkedList::new)));
}
}
Error:
Bad return type in method reference: cannot convert java.util.LinkedList<E> to C
IntegerList has two constructors, one taking zero parameters, the other taking an array; you are trying to pass it a LinkedList.
Convert to an array instead of collecting to a list:
return new IntegerList(
integers.stream()
.map(objectInteger -> new Integer(objectInteger + value))
.toArray(Integer[]::new));
As pointed out by #Hulk, the new Integer is unnecessary: you could use Integer.valueOf instead, but omitting either will still result in boxing:
.map(objectInteger -> objectInteger + value)
Everything is ok with your lambda function, the problem is that you return a LinkedList<Integer> but you don't have constructor for this
Change it like this:
public IntegerList(List<Integer> numbers) {
integers = new LinkedList<>(numbers);
}
Or you can change the stream to return array instead of LinkedList
Integer[] integers = this.integers.stream()
.map(objectInteger -> objectInteger + value)
.toArray(Integer[]::new);
I'm new to Java and I'm having some problems shuffling a list.
I have to write the Iterable class so that when you iterate over the queue it returns the items in a randomly order. That's why I wrote that shuffle method and then I'm calling it inside RandomizedQueueIterator class
import java.util.Iterator;
import java.util.NoSuchElementException;
public class RandomizedQueue<Item> implements Iterable<Item>
{
// instance variables
private Item[] queue;
private int N = 0;
private int R = 0;
// constructor
public RandomizedQueue()
{
queue = (Item[]) new Object[1];
}
// helper functions
private void resize(int capacity)
{
Item[] copy = (Item[]) new Object[capacity];
for (int i = 0; i < N; i++)
copy[i] = queue[i];
queue = copy;
}
private void shrink(int capacity)
{
Item[] copy = (Item[]) new Object[capacity];
int M = 0;
for (int i = 0; i < N; i++)
{
if (queue[i] != null)
copy[M++] = queue[i];
}
queue = copy;
}
// shuffle queue
private void shuffle(Item[] a )
{
int N = a.length;
for (int i = 0; i < N; i++)
{
int r = StdRandom.uniform(i + 1);
Item temp = a[r];
a[r] = a[i];
a[i] = temp;
}
}
// return wether queue is empty
public boolean isEmpty() { return queue.length == 0; }
// return size of queue
public int size() { return queue.length; }
// add item to the queue
public void enqueue(Item item)
{
if (N == queue.length) { resize(N*2); }
queue[N++] = item;
}
// remove and return a random item from the queue
public Item deque()
{
// generate a random index and store item
int random_index;
do {
random_index = StdRandom.uniform(0, N);
} while (queue[random_index] == null);
Item item = queue[random_index];
// delete item from array and increment counter of null items
queue[random_index] = null;
R += 1;
// shrink array if corresponds
if (R == (3/4 * N)) { shrink(N/2); }
// return item
return item;
}
// return a random item from the queue
public Item sample()
{
// generate a random index and store item
int random_index;
do {
random_index = StdRandom.uniform(0, N);
} while (queue[random_index] == null);
Item item = queue[random_index];
// return item
return item;
}
// iteration
public Iterator<Item> iterator()
{
return new RandomizedQueueIterator();
}
private class RandomizedQueueIterator implements Iterator<Item>
{
private int i = 0;
shuffle(queue);
public boolean hasNext()
{
return i < N;
}
public Item next()
{
if (i >= N)
{
throw java.util.NoSuchElementException;
}
return queue[i++];
}
public void remove()
{
throw new UnsupportedOperationException("Invalid operation for array");
}
}
// main method
public static void main(String[] args)
{
RandomizedQueue example = new RandomizedQueue();
example.enqueue(0);
example.enqueue(1);
example.enqueue(2);
example.enqueue(3);
example.enqueue(3);
example.enqueue(3);
example.enqueue(3);
}
}
The output when trying to compile:
2 errors found:
[line: 114] Error: invalid method declaration; return type required
[line: 114] Error: expected
line:114 > shuffle(queue);
Any help would be really appreciated.
Thanks
If you want to run the class you need to put the method call in a main method
public static void main(String...args) {
shuffle(list_test);
}
If you do this you will either define list_test as a static variable or define it inside the main method.
There are a couple of problems. One of the problems is that you are calling the function method "inside" your class not in a function. You should be calling the function outside after you have create the test object.
So In your main. Call:
list_test = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
test testObj = new test();
newList = test.shuffle(list_test); // in the case it returns a new list
where
private void shuffle(int[] a )
// and returns a new list
return shuffled_list
If you only care about shuffling items in your list, use the JDK built-in shuffle() method instead.
There are quite a few things that can be improved. Your class might look like this:
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Random;
// it is standard to use E or T for collections
public class RandomizedQueue<E> implements Iterable<E> {
// most java collections have a default size of 16, set at 2 for testing
private static final int DEFAULT_INITIAL_CAPACITY = 2;
private static final Random GENERATOR = new Random();
// have good variable names
private boolean iterating = false; // to avoid concurrent modification
private E[] queue;
private int size = 0;
#SuppressWarnings("unchecked")
public RandomizedQueue() {
queue = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
// remove and return a random item from the queue
public E dequeue() {
if (iterating) {
throw new ConcurrentModificationException();
}
return dequeue(GENERATOR.nextInt(size));
}
// add item to queue
public void enqueue(E item) {
if (iterating) {
throw new ConcurrentModificationException();
}
if (size == queue.length) {
resize(size * 2);
}
queue[size++] = item;
}
// return whether queue is empty
public boolean isEmpty() {
return size == 0;
}
// iteration
public Iterator<E> iterator() {
return new RandomizedQueueIterator();
}
// return a random item from the queue
public E sample() {
if (isEmpty()) {
throw new NoSuchElementException("trying to sample from empty queue");
}
return queue[GENERATOR.nextInt(size)];
}
// shuffle queue
public void shuffle() {
for (int i = size - 1; i >= 0; i--) {
swap(i, GENERATOR.nextInt(i + 1));
}
}
// return size of queue
public int size() {
return size;
}
// helper functions
private E dequeue(int randomIndex) {
if (isEmpty()) {
throw new NoSuchElementException("trying to remove from empty queue");
}
size--;
// resize if only 1/4 of the queue is full
if (size < queue.length / 4) {
resize(queue.length / 2);
}
// since all get data methods are random, only need to swap on remove
swap(randomIndex, size);
E randomItem = queue[size];
queue[size] = null;
return randomItem;
}
private void resize(int capacity) {
// copyOf is substantially faster since it uses arraycopy which is in native code
queue = Arrays.copyOf(queue, capacity);
}
// swap data at indices i and j
private void swap(int i, int j) {
E temp = queue[j];
queue[j] = queue[i];
queue[i] = temp;
}
private class RandomizedQueueIterator implements Iterator<E> {
private int currentIndex = 0;
private int indexToRemove = -1;
private RandomizedQueueIterator() {
iterating = true;
shuffle();
}
public boolean hasNext() {
return currentIndex < size;
}
public E next() {
if (currentIndex >= size) {
throw new NoSuchElementException();
}
indexToRemove = currentIndex;
E nextElement = queue[currentIndex++];
if (currentIndex == size) {
iterating = false;
}
return nextElement;
}
public void remove() {
if (indexToRemove == -1) {
throw new IllegalStateException();
}
// print for testing
System.out.println("r: " + dequeue(indexToRemove));
currentIndex--;
indexToRemove = -1;
}
}
// main method
public static void main(String[] args) {
int exampleSize = 7;
System.out.println("example 1:");
RandomizedQueue<Integer> example1 = new RandomizedQueue<>();
for (int i = 0; i < exampleSize; i++) {
example1.enqueue(i);
}
System.out.println("size: " + example1.size());
for (int i = 0; i < exampleSize; i++) {
System.out.println("d: " + example1.dequeue());
}
System.out.println("size: " + example1.size());
System.out.println("\nexample 2:");
RandomizedQueue<Integer> example2 = new RandomizedQueue<>();
for (int i = 0; i < exampleSize; i++) {
example2.enqueue(i);
}
System.out.println("size: " + example2.size());
Iterator<Integer> iterator = example2.iterator();
// iterator.remove(); throws IllegalStateException
while (iterator.hasNext()) {
System.out.println("i: " + iterator.next());
iterator.remove();
System.out.println("size: " + example2.size());
// iterator.remove(); should throws IllegalStateException
}
}
}
Use this to give you ideas on how to write your class.
This is something i don't understand, and my professor is busy this week so i can't ask her. Can someone explain to me how to set up a list iterator, and use it to return elements in an ArrayList? thanks. It is the the method "public Iterator iterator()", i've tried my best with it, but i can't complete it.
public class ArrayList<E> implements List<E> {
private E[] elementData;
private int elementCount;
private int capacityIncrement;
private static final int INVALID_INDEX=-1;
private static final int DEFAULT_CAPACITY = 100;
public ArrayList() {
capacityIncrement = 0;
elementData = (E[]) new Object[DEFAULT_CAPACITY];
}
public ArrayList(int capacity) {
this.capacityIncrement = 0;
this.elementData = (E[]) new Object[capacity];
}
public ArrayList(int capacity, int increment) {
this.capacityIncrement = increment;
this.elementData = (E[]) new Object[capacity];
}
public int size() {
return elementCount;
}
public boolean isEmpty() {
if (elementCount != 0) return false;
else return true;
}
public void clear() {
elementCount = 0;
}
public boolean contains(E element) { //check back
for (int i = 0; i < elementCount; i++) {
if (elementData[i].equals(element)) return true; //== vs. .equals
}
return false;
}
public void add(E element) {
elementCount++;
elementData[elementCount] = element;
}
public boolean remove(E element) {
for (int i = 0; i < elementCount; i++) { //while vs. loop
if (elementData[i].equals(element)) {
for (int j = 0; j <= (elementCount - i); j++){
elementData[i] = elementData[i++];
elementCount = elementCount - 1;
return true;
}
}
}
return false;
}
public E elementAt(int index) {
return elementData[index]; //elementdata vs. elementcount
}
public int indexOf(E element) {
for (int i = 0; i < elementCount; i++) //while vs. loop
if (elementData[i].equals(element)) {
return i;
} return INVALID_INDEX;
}
public void insertElementAt(E element, int index) {
elementCount = elementCount + 1;
for (int i = index; i < elementCount; i++) {
elementData[i++] = elementData[i];
}
elementData[index] = element;
//shift right (look at notes)
}
public void removeElementAt(int index) {
for (int i = index; i < elementCount; i++) {
elementData[i] = elementData[i++];
}
elementCount = elementCount - 1;
}
public void setElementAt(E element, int index) {
elementData[index] = element;
}
public void removeDuplicates() {
for (int i = 0; i < elementCount; i++) {
for (int j = 0; j < elementCount; j++) {
if (elementData[i].equals(elementData[j])) {
elementData[i] = elementData[i++];
elementCount = elementCount - 1;
}
}
}
}
public void trimToSize() { //don't need to add trims to removing methods??
}
public Iterator<E> iterator() {
Iterator itr = new list.iterator();
while (itr.hasNext()) {
}
/**
*
* #return a list iterator of the elements
* in this list (in proper sequence).
*/
}
public Iterator<E> iterator(int index) {
throw new UnsupportedOperationException("Not supported yet.");
}
private static class ArrayListIterator<E> implements Iterator<E> {
private ArrayListIterator(ArrayList c) {
/**
* Returns a list iterator of the elements in this list (in proper sequence).
* #param c list to be iterated upon
*/
elementData=c;
}
}
}
Iterator is just an interface that specifies an implementing class must provide next() and hasNext().
A simple first cut implementation would be to make your array list implement the Iterator interface.
You would add a "currentIndex" member and a method like
Iterator<E> iterator() { return this; }
next() and hasNext() would use the currentIndex and the array size as appropriate.
Obviously this breaks if you want to have more than one iterator over the same collection, so the next step would be to refactor the iterator stuff into a separate class.
In your public Iterator iterator() method you are returning an iterator. So
public Iterator<E> iterator() {
return this.iterator();
}
will do the job.