Insert in a sorted Array-Queue - java

I'm working on sorted Queues like a Priority Queue. I already did it with a List, and it already worked great. Now I'd like to do it with a array. But I have a little logical Problem with add a new Element and insert it into the sorted array.
The final output should be like that:
Priority: 5 Value: x
Priority: 4 Value: iso
.... (and so on)
So the Element with the highest Priorithy should be on index = 0.
I just don't know (and yes I know it's really simply to switch it, but I just can't do it :/) how to do it...
I already tried a few things but I'm stuck... :/ can please anyone help?
Here's my code:
public class Queue {
private QueueElem[] a;
public Queue(int capacity)
{
QueueElem[] tempQueue = new QueueElem[capacity];
a= tempQueue;
}
public void enqueue(int p, String v)
{
QueueElem neu = new QueueElem(p,v);
int i=0;
while(i<a.length)
{
if (a[i] == null)
{
a[i] = neu;
break;
}
i++;
}
}
public void writeQueue()
{
int i=0;
while((i< a.length) && (a[i] != null))
{
System.out.println("Priority: " + a[i].priority + " Value: " + a[i].value);
i++;
}
}
public static void main(String args[])
{
Queue neu = new Queue(10);
neu.enqueue(4,"iso");
neu.enqueue(2,"abc");
neu.enqueue(5,"x");
neu.enqueue(1,"abc");
neu.enqueue(4,"bap");
neu.enqueue(2,"xvf");
neu.enqueue(4,"buep");
}
}//end class Queue
class QueueElem {
int priority;
String value = new String();
public QueueElem(){ }
public QueueElem(int p, String v)
{
this.priority = p;
this.value = v;
}
public int getPrio()
{
return this.priority;
}
public String getValue()
{
return this.value;
}
}

It would be better if you interpreted your array as a max-heap. That is the typical way to implement priority queue.
What you're looking for, if you're trying to maintain a sorted array for your priority queue, is to implement insertion sort (sort of; you don't have an unsorted array to start with. You have an empty array that you simply add to, while maintaining a sorted order). Every time you insert a new element, you will iterate through the array to find the correct spot and then insert it there, after shifting the elment currently at that spot, and everything after it one spot down. Note that this is not as performant as implementing this using a heap, since at worst you have O(n) performance every time you insert, whereas with a heap you have O(logn).

I don't understand why anyone would want to work with raw arrays... especially now that you have implemented it with a List.
If you want to see how to insert an element in a raw array, look in the code of ArrayList, since underneath it uses a raw array. You'll have to move all the elements to right of the insertion point, which you could copy in a loop, or by using System.arraycopy(). But the nastiest part is that you will likely have to create a new array since the array size increases by one when you add an element (it depends if you are using an array that has exactly the size of your data, or a larger array, as is done in ArrayList).

Related

What is the fastest way to fill an ArrayList with null in java?

I want a List of n Sets of Integers and initially this list should be filled with null.
A lot of the Sets will be initialised later, and some will remain null.
I have tried different methods to implement this, some of them are included here:
List<HashSet<Integer>> List_of_Sets = Arrays.asList(new HashSet[n]);
ArrayList<HashSet<Integer>> List_of_Sets = new ArrayList<>(n);
while(n-- > 0) List_of_Sets.add(null);
Is there a faster way to do this?
For clarification an example for arrays would be Arrays.fill() used to be slower than:
/*
* initialize a smaller piece of the array and use the System.arraycopy
* call to fill in the rest of the array in an expanding binary fashion
*/
public static void bytefill(byte[] array, byte value) {
int len = array.length;
if (len > 0){
array[0] = value;
}
//Value of i will be [1, 2, 4, 8, 16, 32, ..., len]
for (int i = 1; i < len; i += i) {
System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i) : i);
}
}
^above code is from Ross Drew's answer to Fastest way to set all values of an array?
Is there a faster way to do this?
As far as I am aware, no. Certainly, there is no easy way that is faster.
Based on how it works, I think (but I have not tested) that the Arrays.asList(new HashSet[n]) should be the fastest solution.
It would be possible to implement a custom List implementation that is like an ArrayList but is pre-initialized to N null values. But under the hood the initialization will be pretty much identical with what happens in the List implementation that asList returns. So I doubt that any performance improvements would be significant ... or worth the effort.
If you want to be sure of this, you could write a benchmark of the various options. However, I don't think this is the right approach in this case.
Instead I would recommend benchmarking and profiling your entire application to determine if operations on this list are a real performance hotspot.
If it is not a hotspot, my recommendation would be to just use the Arrays.asList approach and spend your time on something more important.
If it is a hotspot, you should consider replacing the List with an array. From your earlier description it seemed you are going to use the List like an array; i.e. using positional get and set operations, and no operations that change the list size. If that is the case, then using a real array should be more efficient. It saves memory, and avoids a level of indirection and (possibly) some bounds checking.
One reason not to do this would be if you needed to pass the array to some other code that requires a List.
If resizing is not important to you then implementing your own list might be fast. It might also be buggy. It would at least be interesting to benchmark compared to Java's lists. One strange effect that you might see is that standard lists might be optimised by the JIT sooner, as they could be used internally by Java's standard library.
Here is my attempt, although I suggest you don't use it. Use a standard list implementation instead.
import java.util.*;
public class FastListOfNullsDemo {
public static void main(String[] args) {
Set<Integer>[] arr = new Set[100_000]; // all set to null by default.
List<Set<Integer>> myList = new ArrayBackedList<>(arr);
myList.set(3, new TreeSet<Integer>());
myList.get(3).add(5);
myList.get(3).add(4);
myList.get(3).add(3);
myList.get(3).add(2);
myList.get(3).add(1);
// Let's just print some because 100,000 is a lot!
for (int i = 0; i < 10; i++) {
System.out.println(myList.get(i));
}
}
}
class ArrayBackedList<T> extends AbstractList<T> {
private final T[] arr;
ArrayBackedList(T[] arr) {
this.arr = arr;
}
#Override
public T get(int index) {
return arr[index];
}
#Override
public int size() {
return arr.length;
}
#Override
public T set(int index, T value) {
T result = arr[index];
arr[index] = value;
return result;
}
}
Another possibility would be implementing an always-null, fixed-size list. Use that to initialise the ArrayList. I won't promise that it is fast but you could try it out.
import java.util.*;
public class FastListOfNullsDemo {
public static void main(String[] args) {
List<Set<Integer>> allNull = new NullList<>(100_000);
List<Set<Integer>> myList = new ArrayList<>(allNull);
myList.set(3, new TreeSet<Integer>());
myList.get(3).add(5);
myList.get(3).add(4);
myList.get(3).add(3);
myList.get(3).add(2);
myList.get(3).add(1);
System.out.println(myList.size());
// Let's just print some because 100,000 is a lot!
for (int i = 0; i < 10; i++) {
System.out.println(myList.get(i));
}
}
}
class NullList<T> extends AbstractList<T> {
private int count;
NullList(int count) {
this.count = count;
}
#Override
public T get(int index) {
return null;
}
#Override
public int size() {
return count;
}
}

How to write an implementation class for a Bag (or Multiset) ADT?

I have an assignment in which I need to write an implementation class for a Bag (or Multiset) ADT. Problem is, the assignment is worded in a way that's hard to follow and I'm not sure what exactly I need to do.
Here is the assignment description and here is the interface I was provided. This is my implementation class so far. I haven't written any of my methods yet because I'm not sure where to go from here, especially in regards to the 3 different constructors.
package Bags;
import java.io.*;
public class ConBag implements Bag, Serializable {
private String[] items; // The items in the bag
private int itemCount; // The number of items
private int size; // The size of the bag
// This constructor creates a new empty bag able to hold 100 items.
public ConBag ( ) {
this(100);
}; // Constructor
// This constructor creates a new bag with a specified capacity.
public ConBag ( int size ) {
items = new String[size];
}; // Constructor
// This constructor takes an array of Strings and copies them into a bag of 100 or fewer items.
public ConBag ( String[] items ) {
}; // Constructor
public void add ( String item ) {
try{
if(!contains(item) && (!(size == items.length))){
items[itemCount] = item;
itemCount++;
}
}catch (NoSpaceException exception) {
System.out.println("Bag is full.");
}
}; // Add
public void remove ( String item ) {
for (int i=0; i<size; i++) {
if (contains(item)) {
items[i] = items[itemCount-1];
}else {
NoItemException exception;
System.out.println("Item not in bag.");
}
}
};
public int cardinality ( ) {
return itemCount;
};
public boolean contains ( String item ) {
for (int i=0; i<itemCount; i++) {
if(items[i].equals(item))
return true;
}
return false;
};
public int count ( String item ) {
int count;
return count;
};
public String draw ( ) {
};
}
I feel like I'm missing something important, but I don't know what. I already have NoItemException and NoSpaceException, but I don't think I need to include them in this post as they're pretty basic. Any help or a nudge in the right direction would be great. Thanks!
You need to allow duplication, therefore using String array as a data structure makes things difficult. It's better to use a map where the key is a String and the value is an Integer.
It's unclear what is the limit of the room, so, for now you can define a private member called room, which will be int and whenever you intend to add a String, check cardinality against room. If it's smaller, then increment the value of the map entry if exists. If it did not, then just create it with a value of 1.
remove should check for contains. If the Map you have does not contain the item, throw an exception. Otherwise decrement the value of the map entry if it's higher than 1. If it is 1, then just remove it from the map.
To calculate cardinality traverse the map and calculate the sum of the values.
contains should be simple, you will just have to call a method of your map. count should be simple as well.
draw is interesting. First, calculate cardinality, use it as the unreachable upper bound of your randomization and initialize a sum and start traversing the map. On each iteration increase sum (which is 0 before the loop) with the value of the map entry. If the randomized number is smaller than sum, then call remove passing the key of the item and exit the loop.
EDIT
If you need to do this with an array of String items, then you can do so, but you will also need to store an integer for each String, that would be another array and the easiest representation would be to ensure that every item in the String array would be associated to the int value in the int array at the same index. Not too elegant, but can be used. Now, in this case you could not use Map methods, but will need to implement stuff yourself.

Can you have collections without storing the values in Java?

I have a question about java collections such as Set or List. More generally objects that you can use in a for-each loop. Is there any requirement that the elements of them actually has to be stored somewhere in a data structure or can they be described only from some sort of requirement and calculated on the fly when you need them? It feels like this should be possible to be done, but I don't see any of the java standard collection classes doing anything like this. Am I breaking any sort of contract here?
The thing I'm thinking about using these for is mainly mathematics. Say for example I want to have a set representing all prime numbers under 1 000 000. It might not be a good idea to save these in memory but to instead have a method check if a particular number is in the collection or not.
I'm also not at all an expert at java streams, but I feel like these should be usable in java 8 streams since the objects have very minimal state (the objects in the collection doesn't even exist until you try to iterate over them or check if a particular object exists in the collection).
Is it possible to have Collections or Iterators with virtually infinitely many elements, for example "all numbers on form 6*k+1", "All primes above 10" or "All Vectors spanned by this basis"? One other thing I'm thinking about is combining two sets like the union of all primes below 1 000 000 and all integers on form 2^n-1 and list the mersenne primes below 1 000 000. I feel like it would be easier to reason about certain mathematical objects if it was done this way and the elements weren't created explicitly until they are actually needed. Maybe I'm wrong.
Here's two mockup classes I wrote to try to illustrate what I want to do. They don't act exactly as I would expect (see output) which make me think I am breaking some kind of contract here with the iterable interface or implementing it wrong. Feel free to point out what I'm doing wrong here if you see it or if this kind of code is even allowed under the collections framework.
import java.util.AbstractSet;
import java.util.Iterator;
public class PrimesBelow extends AbstractSet<Integer>{
int max;
int size;
public PrimesBelow(int max) {
this.max = max;
}
#Override
public Iterator<Integer> iterator() {
return new SetIterator<Integer>(this);
}
#Override
public int size() {
if(this.size == -1){
System.out.println("Calculating size");
size = calculateSize();
}else{
System.out.println("Accessing calculated size");
}
return size;
}
private int calculateSize() {
int c = 0;
for(Integer p: this)
c++;
return c;
}
public static void main(String[] args){
PrimesBelow primesBelow10 = new PrimesBelow(10);
for(int i: primesBelow10)
System.out.println(i);
System.out.println(primesBelow10);
}
}
.
import java.util.Iterator;
import java.util.NoSuchElementException;
public class SetIterator<T> implements Iterator<Integer> {
int max;
int current;
public SetIterator(PrimesBelow pb) {
this.max= pb.max;
current = 1;
}
#Override
public boolean hasNext() {
if(current < max) return true;
else return false;
}
#Override
public Integer next() {
while(hasNext()){
current++;
if(isPrime(current)){
System.out.println("returning "+current);
return current;
}
}
throw new NoSuchElementException();
}
private boolean isPrime(int a) {
if(a<2) return false;
for(int i = 2; i < a; i++) if((a%i)==0) return false;
return true;
}
}
Main function gives the output
returning 2
2
returning 3
3
returning 5
5
returning 7
7
Exception in thread "main" java.util.NoSuchElementException
at SetIterator.next(SetIterator.java:27)
at SetIterator.next(SetIterator.java:1)
at PrimesBelow.main(PrimesBelow.java:38)
edit: spotted an error in the next() method. Corrected it and changed the output to the new one.
Well, as you see with your (now fixed) example, you can easily do it with Iterables/Iterators. Instead of having a backing collection, the example would've been nicer with just an Iterable that takes the max number you wish to calculate primes to. You just need to make sure that you handle the hasNext() method properly so you don't have to throw an exception unnecessarily from next().
Java 8 streams can be used easier to perform these kinds of things nowadays, but there's no reason you can't have a "virtual collection" that's just an Iterable. If you start implementing Collection it becomes harder, but even then it wouldn't be completely impossible, depending on the use cases: e.g. you could implement contains() that checks for primes, but you'd have to calculate it and it would be slow for large numbers.
A (somewhat convoluted) example of a semi-infinite set of odd numbers that is immutable and stores no values.
public class OddSet implements Set<Integer> {
public boolean contains(Integer o) {
return o % 2 == 1;
}
public int size() {
return Integer.MAX_VALUE;
}
public boolean add(Integer i) {
throw new OperationNotSupportedException();
}
public boolean equals(Object o) {
return o instanceof OddSet;
}
// etc. etc.
}
As DwB stated, this is not possible to do with Java's Collections API, as every element must be stored in memory. However, there is an alternative: this is precisely why Java's Stream API was implemented!
Streams allow you to iterate across an infinite amount of objects that are not stored in memory unless you explicitly collect them into a Collection.
From the documentation of IntStream#iterate:
Returns an infinite sequential ordered IntStream produced by iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc.
The first element (position 0) in the IntStream will be the provided seed. For n > 0, the element at position n, will be the result of applying the function f to the element at position n - 1.
Here are some examples that you proposed in your question:
public class Test {
public static void main(String[] args) {
IntStream.iterate(1, k -> 6 * k + 1);
IntStream.iterate(10, i -> i + 1).filter(Test::isPrime);
IntStream.iterate(1, n -> 2 * n - 1).filter(i -> i < 1_000_000);
}
private boolean isPrime(int a) {
if (a < 2) {
return false;
}
for(int i = 2; i < a; i++) {
if ((a % i) == 0) {
return false;
}
return true;
}
}
}

Adding elements to array in alphebetical order

I'm writing a program which adds telephone entries into a staff phone directory, I want to add the elements to the array in alphabetical order (using surnames) rather than adding the elements then calling Arrays.sort every time a new entry is added, as that would be less efficient. Here is some code I have so far, I'm not sure how to compare each element in the array with the following one and so forth.
public class ArrayDirectory implements Directory {
Entry [] directory = new Entry [50];
#Override
public void addEntry(String initials, String surname, int extension) {
//Entries are added here in alphabetical order
}
Here is my Entry class -
public class Entry {
private String initals,surname;
private int extention;
public Entry(String initals, String surname, int extention){
this.initals = initals;
this.surname = surname;
this.extention = extention;
}
public String getInitals(){
return initals;
}
public String getSurname(){
return surname;
}
public int getExtention(){
return extention;
}
}
Any suggestions, do I override compareTo? Thanks
edit - should have noted I have been asked to use an array. Sorry for the confusion.
Edit 2: updated my addEntry method and overriden compareTo in Entry -
public void addEntry(String initials, String surname, int extension) {
for (int i = 0; i < directory.length; i++) {
if (directory[i] != null) {
int y = directory[i].getSurname().compareTo(surname);
if (y == 1) {
int position = i;
break;
}
} else if (directory[i] == null) {
int position = i;
break;
}
}
}
And my compareTo method -
public int compareTo(Entry other) {
return this.surname.compareTo(other.getSurname());
}
I'm not sure how to shift the elements in the array to the right after I have found the correct position? Thank you for all of you help.
If you dont have to use an array then your using the wrong data structure.
No matter what path you need to implement Comparable:
public class Entry implements Comparable<Entry>{
..
#Override
public int compareTo(Entry other) {
// TODO Auto-generated method stub
return this.surname.compareTo(other.getSurname());
}
..
Consider using a SortedSet:
Set<Entry> map = new TreeSet<Entry>();
map.add(new Entry("JEH", "Hamlet", 123));
map.add(new Entry("AAC", "Adams", 123));
map.add(new Entry("FAM", "Monti", 321));
That will print in the desired order. If you must use an Array then you need to sort it upon insert.
You could make Entry comparable and implement the compareTo in it. But you don't really have to in this case because String is already comparable.
Since this is a homework, I think it will be best to just give you some suggestions on how to proceed, instead of handing you the code -
In your method you do not need to sort the array, you just need to insert it at the correct location in the array.
loop through the array starting at the first index
as you pass through each element in the array, you will have to check following two conditions
is the element null
is the surname of current element greater than surname-argument to the method
as soon as you find the element that satisfies any of the above conditions, record the index and break the loop
then, starting at that index shift the rest of elements to the right
and finally create a new instance of Entry for the provided arguments and set it at that index
Note: This doesn't take care of the situation where you are out of the space in the array.
Update:
I think you mixed up my answer and #David Wallace's answer. It wasn't my suggestion to implement compareTo. Also, it's great that you at least gave it a try and came back.
int position = -1; //declare the position outside (if declared inside, it's not visible outside the loop)
for (int i = 0; i < directory.length; i++) {
// position = i; just assign value of i inside the loop
}
//use the position after the loop
int j = position; // start at position
Entry temp = null; // temp will temporarily hold the entry at the next index
while(true) {
temp = directory[j + 1]; // since we need move entry at j to j+1, first we need save the entry at j+1
directory[j + 1] = directory[j]; // entry at j to j+1
if(temp == null) { // if the next entry is null, don't really need to move no more, so break
break;
}
}
// finally place new entry at index position
directory[position] = //the new Entry
Make Entry implement Comparable<Entry> and write the appropriate compareTo method in your Entry class. Then, in your insert method, you want to
Use Arrays.binarySearch to find the right place in the array to insert your the entry.
Use System.arraycopy to shift everything in the array that's after the appropriate location one place to the right.
Set the appropriate entry.
You'll want to check out the Javadoc for Arrays.binarySearch and System.arraycopy.
Firstly, never use arrays unless you absolutely have to. Use Collecctions instead - they are far easier to deal with and have support for lots of operations you commonly want to perform on groups of things.
In your case, a TreeSet would be a good choice. If you want to sort the entries by surname only in this usage (and not generally), you can pass a customer Comparator to the constructor:
Set<Entry> directory = new TreeSet<>(new Comparator<Entry>() {
#Override
public int compare(Entry o1, Entry o2) {
return o1.getSurname().compareTo(o2.getSurname());
}
});
If your always want to sort Entry objects using surname, have your Entry class implement Comparable<Entry> and move the code into the compareTo() method of the Entry class.

How to create extensible dynamic array in Java without using pre-made classes?

Yeah, it's a homework question, so givemetehkodezplsthx! :)
Anyway, here's what I need to do:
I need to have a class which will have among its attributes array of objects of another class. The proper way to do this in my opinion would be to use something like LinkedList, Vector or similar. Unfortunately, last time I did that, I got fire and brimstone from my professor, because according to his belief I was using advanced stuff without understanding basics.
Now next obvious solution would be to create array with fixed number of elements and add checks to get and set which will see if the array is full. If it is full, they'd create new bigger array, copy older array's data to the new array and return the new array to the caller. If it's mostly empty, they'd create new smaller array and move data from old array to new. To me this looks a bit stupid. For my homework, there probably won't be more that 3 elements in an array, but I'd like to make a scalable solution without manually calculating statistics about how often is array filled, what is the average number of new elements added, then using results of calculation to calculate number of elements in new array and so on.
By the way, there is no need to remove elements from the middle of the array.
Any tips?
class test {
private Object[] objects;
private int size;
public test() {
objects = new Object[10];
size = 0;
}
public void push(Object o) {
if (objects.length == size) {
throw new RuntimeException("This wouldn't happen if I didn't have to reinvent the wheel");
}
objects[size] = o;
size++;
}
public Object pop() {
size--;
Object o = objects[size];
objects[size] = null;
return o;
}
}
Just kidding. I think you're best bet is to implement your own linked list and then use that in your class. Something like:
class Element {
Object val;
Element next;
Element prev;
public Element(Object val, Element next, Element prev) {
this.val = val;
this.next = next;
this.prev = prev;
}
}
class LinkedList {
Element head;
Element tail;
public void add(Object o) {
Element el = new Element(o, null, tail);
tail.next = el;
}
public Object remove() {
Element o = tail;
tail = o.prev;
tail.next = null;
return o.val;
}
}
One thing you will want to do is when you need to grow the size of your array create an array that is twice the size of the old array. Likewise, if you need to shrink the size of hte array, only do it once the array is half full.
This will make it so you have to do far less array copies.
Doing this will make it necessary to keep a variable that keeps track of the actual size of the array because the length of the array will not accurately represent the actual size.
To copy an existing array into a smaller or larger one, you may find System#arrayCopy() useful.
Kickoff example:
Object[] originalArray = new Object[3];
// ...
Object[] resizedArray = new Object[originalArray.length + 2]; // Grow with 2.
System.arrayCopy(originalArray, 0, resizedArray, 0, originalArray.length);
This will copy the items over the entire length of originalArray into the beginning of resizedArray. The 2 slots at end of resizedArray are still null so that you can use it for other items.
This must get you started. Good luck :)
Is it for a data structures class ? Sounds like your professor expects you to implement your own Linked List data structure or something similar instead of using the one Java provides. Google and your text book(s) are your friend.
If I recall correctly, the ArrayList class works by having a fixed size array (with an initial capacity of whatever you set) that resizes in pretty much the way you described when it's full.
You could use a linked list, though by the sounds of it your professor wants you to program this stuff by yourself, so create your own class demonstrating you know how it works?
i think its really easy way :p which we cant do in C but can do in java
package javaapplication21;
import java.util.Scanner;
public class JavaApplication21 {
public static void main(String[] args) {
int a;
Scanner obj=new Scanner(System.in);
System.out.print("Enter array size=");
a=obj.nextInt();
int b[]=new int[a];
for(int i=0;i<b.length;i++){
System.out.println(b[i]+i);
}
}
}

Categories

Resources