java.util.PriorityQueue's elements does not move up on poll() - java

I am implementing a BFS on a graph, where nodes are marked by objects of a State class (I have implemented an implicit equals to method for comparison).
I have implemented my queue using a PriorityQueue with a comparator that returns 1 since I want to expand the program to handle DFS, Astar etc, which I can do by just changing the logic inside the comparator
Here is the relevant code:
//BFSComparator.java
import java.util.Comparator;
public class BFSComparator implements Comparator<State>{
#Override public int compare(State x, State y) {
return 1;
}
}
//solver.java
Comparator comparator = new BFSComparator();
PriorityQueue<State> frontierList = new PriorityQueue<State>(500,comparator); //List of nodes to be expanded
frontierList.add(seed state0);
while (!frontierList.isEmpty()){
curState = frontierList.poll();
//handle, expand and add child states to frontierList
While iterating through the list and printing elements present, I found that some elements do not move up the rank (example, {a,b,c,d,e} on poll becomes {b,e,c,d} on poll() rather than {b,c,d,e}), and hence, it does not perform FIFO.
for(State x:frontierList) {
//print x
}
1) Is there something wrong with my comparator?
2) Is there a better way to do this generically? i.e. , a better Container than priority queue that I can just add to while changing the logic behind the sorting rather than use Queues and stacks with difference call names like push and pop? This would be helpful when I sort them later based on heuristics. Or should I just use a linked list and perform an insertion sort based approach?
EDIT:
I'd like to make it a little more clear. I'm trying to implement a collection that I can throw things at with a common add(State) or State x = remove() irrespective of DFS or BFS (FIFO or LIFO) or other priority based algorithms like A-Star and Beam Search.
I'm probably going to extend collection and implement add and other methods.

public int compare(State x, State y)
This method return a positive value means x > y, a negative value means x < y and 0 means x==y.
I thouht you should use Queue to declare frontierList instead
When you need DFS, use LinkedList<State>
When you need BFS, use PriorityQueue<State> and a Comparator<State> return the min or max State you want

Related

How to implement Union-Find using linked lists?

I need to write a piece of code using the Kruskal algorithm, which in turn needs the Union-Find algorithm.
This includes the methods Make-Set(x), Find-Set(x) and Union(x, y).
I need to implement them using linked lists, but I am not sure of how to start with the Make-Set method.
The Make-Set Method should create a set and make the first element into a key (to compare sets). How exactly would I declare a key using linked lists?
Shortly put: How do I implement this pseudo code for linked lists in Java?
Make-Set(x)
x.p = x
x.rank = 0
Thanks for your help in advance!
I've heard this referred to in the past not as "Union-Find" but as a disjoint set. It isn't exactly a linked list, since the nodes do have a link, but they aren't necessarily linked up in a linear fashion. It's more like a tree where each node has a pointer to its parent and you can walk up the tree to the root.
I don't have much time right now, but here's a quick sketch of how I would implement it in Java:
class Disjoint {
Disjoint next;
Disjoint findSet() {
Disjoint head = this;
if (next != null) {
head = next.findSet();
next = head;
}
return head;
}
void union(Disjoint other) {
Disjoint us = this.findSet();
Disjoint them = other.findSet();
us.next = them;
}
}
Creating an instance is your Make-Set. What you call Find-Set I would call find head or find leader, maybe find identity. I've called it findSet here, though. It walks the chain to find the root of the tree. It also performs an optional operation; it snaps all the links on the way back out of the recursive call so that they all point directly at the root. This is an optimization to keep the chains short.
Finally, Union is implemented just by assigning one root's next pointer to point at the other set. I'm not sure what you intended with rank; if it's the size of the set, you can add a field for that and simply sum them when you union two sets. But you initialize it to 0 for a new set when I would expect it to be initialized to 1.
Two nodes a and b belong to the same set if a.findSet() == b.findSet(). If you need the nodes to carry some data, make the class generic and provide the data to the constructor, and add a getter:
class Disjoint<T> {
Disjoint<T> next;
T data;
public Disjoint(final T data) {
this.data = data;
}
public T getData() {
return data;
}
// rest of class identical except Disjoint replaced with Disjoint<T> everywhere
}

creating custom iterator with unit tests

I am learning programming and new to this domain as i am have a mechanical background.
Yesterday I received a problem statement from prof. where he provided us an custom Iterator which is designed to iterate over given elements alternatively.
Alternate Iterator code is as following.
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class AlternatingIterator<E> implements Iterator{
private final Queue<E> queue = new LinkedList<>();
public AlternatingIterator(Iterator<E> ... iterators) {
for(Iterator<E> iterator : iterators) {
while(iterator.hasNext())
queue.add(iterator.next());
}
}
#Override
public boolean hasNext() {
return queue.isEmpty() ? false : true;
}
#Override
public Object next() {
return queue.poll();
}
}
Now, The AlternatingIterator should alternate in order between the iterators it receives in its constructor. For example if constructed with three iterators [a,b,c], [1,2] and [x,y,z], the iterator should produce the elements in this order ‘a, 1, x, b, 2, y, c, z’
Also i have to Write unit tests for the ‘hasNext’ and ‘next’ methods.
Can we implement any other data structure than queue?
I am completely blown off and tired to understand how to solve this challenge but very confused here. If you guys can help me then i can learn important concept very quickly.
Thank you in advance and any help is appreciated.
Of course, we can use anything we can imagine. The following implementation alternates dynamically. Instead of using a queue, I store all the received iterators in an array:
import java.util.Iterator;
/**Alternates on the given iterators.*/
public class AlternatingIterator<E> implements Iterator {
/**Stores the iterators which are to be alternated on.*/
private Iterator<E>[] iterators;
/**The index of iterator, which has the next element.*/
private int nextIterator = 0;
/**Initializes a new AlternatingIterator object.
* Stores the iterators in the iterators field.
* Finds the first iterator with an available element.*/
public AlternatingIterator(Iterator<E> ... iterators) {
this.iterators = iterators;
if (!iterators[0].hasNext())
findNextIterator();
}
#Override
public boolean hasNext() {
return iterators[nextIterator].hasNext();
}
#Override
public Object next() {
E element = iterators[nextIterator].next();
findNextIterator();
return element;
}
/**Steps on iterators, until one has next element.
* It does not step on them infinitely, stops when
* the lastly used iterator is reached.*/
private void findNextIterator() {
int currentIterator = nextIterator;
// Finding iterator with element remaining.
do {
stepNextIterator();
} while (!iterators[nextIterator].hasNext() && nextIterator != currentIterator);
// If it gets around to the same iterator, then there is no iterator with element.
}
/**Increases the nextIterator value without indexing out of bounds.*/
private void stepNextIterator() {
nextIterator = (nextIterator + 1) % iterators.length;
}
}
But the same could be made statically using a queue, enqueuing all the elements from the iterators, having only that one queue as in your (your prof's) code.
#Andy Turner: Collecting the elements from the iterator results in not relying on the source collection the entire time until the last element is not obtained. Sure, from Java8 we use Streams, which won't gift us concurrent exceptions, but before Java8, buffering an/more iterator into a collection could have been safer in my opinion.
EDIT: you wrote then we can use the iterator of that given collection. Yeah, I totally forgot that, implementing an iterator for a simple queue is for sure pointless :)
A queue is helpful here, but not in the way you are using it.
There is no real point in copying all the elements from the iterators provided to the constructor into a queue, and then implementing a custom iterator from this queue: if you are going to put the elements into a collection which already implements Iterable, you may as well just use that Iterable's iterator.
But this is also probably not the point of the exercise: you can do this lazily with respect to consuming the input iterators. (Besides, what if one of the iterators is infinite...)
The idea I would suggest is to make a queue of iterators, not elements. Here is a description of how you could do it; I don't want to give you code to spoil your learning experience:
In your constructor, put the iterators from the parameter into a queue.
To implement hasNext(), pop iterators off the head of the queue for which hasNext() is false; stop when the iterator at the head of the queue has a next element (in which case return true), or the queue is empty (in which case return false).
To implement next(), pop the head iterator out of the queue, and get its next element: this is what you will return. But, before you do, if the iterator has more elements, push it onto the tail of the queue (doing this means that you will look at the next iterator on the next iteration).

Get max element in a Queue | Java

Is there an alternative way to get the max element in a Queue (Java)?
(Please provide alternative approaches )
import java.util.*;
public class MaxQueueElement<E extends Comparable<E>> {
public MaxQueueElement(Queue<E> queue){
E max= queue.peek(); // initialize max with head of queue
for(E e : queue){
if(e.compareTo(max) > 0){
max = e;
}
}
System.out.println(max);
}
}
The get-max operation on a queue can be implemented in amortized O(1) time by maintaining the candidates for the max value in a separate double-ended queue (Deque).
On enqueue (or offer) operation, we check whether there are any elements at the back of the Deque which are lesser in value than the element being enqueued. These values can simply be removed – for these can never be the maximum value going forward.
On dequeue (or poll) operation, we check whether the first element in the Deque is equal to the first element in the regular queue and if yes, remove it too.
The max element is simply the first element of the Deque.
All operations have amortized O(1) time complexity.
Here's an implementation in Java:
public class QueueWithMax<T extends Comparable<T>> {
Queue<T> queue;
Deque<T> cMax; // candidates for Max value
public QueueWithMax() {
queue = new LinkedList<>();
cMax = new LinkedList<>();
}
public void offer(T element) {
queue.offer(element);
while (!cMax.isEmpty() && element.compareTo(cMax.peekLast()) > 0) {
cMax.pollLast();
}
cMax.offerLast(element);
}
public T poll() {
if (cMax.peekFirst().equals(queue.peek()))
cMax.pollFirst();
return queue.poll();
}
public T getMax() {
return cMax.peekFirst();
}
}
The only way to access all elements in a Queue is to use the iterator() method - you can't (generally) access the elements by index (as in, some implementations might, but Queue doesn't inherently).
As such, all you can do is to iterate the elements one at a time, storing the current maximum element. This is exactly what you're doing here.
There is nothing wrong with your algorithm - but the way you've implemented it could be improved:
Don't do this in the constructor of a class - you don't need to construct a new instance of anything, as the maximum value already exists. Do it in a (static) method.
Don't print out the result - that's of no use to man or beast. Return it to the caller.
Handle the cases where the queue is empty and may contain nulls. (Look at the Javadoc of Collections.max for ideas)
I'm taking a computer science class, and we aren't allowed to use the for each loop. I'm not sure if it's the same with you. Note that the for each loop kind of defeats the purpose of a Queue since you want to only be handling the front and end of a queue. In my class specifically, we also want to have the queue be at it's original state before it was passed into the method without using an extra auxiliary data structure. Here's how I would go about it on a test:
public E findMaxQueueElement(Queue<e> queue) { //my test would ask me to return the max value
E max = queue.remove();
queue.add(max); //add it back to the end
for(int i=0; i<queue.size()-1; i++) {
E current = queue.remove();
if (current.compareTo(max) > 0) {
max = current;
}
queue.add(current);
}
return max;
}
With the limitations I provided, this should work. I hope this helps.
You can use Java 8's stream to sort the Queue, it internally uses the same algorithm but will result in less noisy code, e.g.:
public void MaxQueueElement(Queue<E> queue){
Optional<E> max = queue.stream()
.max(Comparable::compareTo);
if(max.isPresent()){
System.out.println(max.get());
}
}
Another approach would be to use PriorityQueue with comparator and get the first element from it. e.g.:
public void MaxQueueElement2(Queue<E> queue){
PriorityQueue<E> pQueue = new PriorityQueue<>((E e1, E e2)->e1.compareTo(e2));
pQueue.addAll(queue);
System.out.println(pQueue.peek());
}
Unless the queue is not some special sorted queue like PriorityQueue, from the algorithmic point of view there is no better way. Since the queue does not have any intrinsic sorting properties, you have to check all the elements of the queue before you find one.
The code is more or less OK. It will fail if the queue contains null. This is normally not the case, but may happen.
The MaxQueueElement construct is somewhat strange.
I think you can also make use of
Collections.max(queue) in case of queue

Efficient search in datastructure ArrayList

I've an ArrayList which contains my nodes. A node has a source, target and costs. Now I have to iterate over the whole ArrayList. That lasts for for over 1000 nodes a while. Therefore I tried to sort my List by source. But to find the corresponding pair in the List I tried the binary search. Unfortunately that works only if I want to compare either source or target. But I have to compare both to get the right pair. Is there another possibility to search an ArrayList efficient?
Unfortunately, no. ArrayLists are not made to be efficiently searched. They are used to store data and not search it. If you want to merely know if an item is contained, I would suggest you use HashSet as the lookup will have a time complexitiy of O(1) instead of O(n) for the ArrayList (assuming that you have implemented a functioning equals method for your objects).
If you want to do fast searches for objects, I recommend using an implementation of Dictionnary like HashMap. If you can afford the space requirement, you can have multiple maps, each with different keys to have a fast lookup of your object no matter what key you have to search for. Keep in mind that the lookup also requires implementing a correct equals method. Unfortunately, this requires that each key be unique which may not be a brilliant idea in your case.
However, you can use a HashMapto store, for each source, a List of nodes that have the keyed source as a source. You can do the same for cost and target. That way you can reduce the number of nodes you need to iterate over substantially. This should prove to be a good solution with a scarcely connected network.
private HashMap<Source, ArrayList<Node>> sourceMap = new HashMap<Source, ArrayList<Node>>();
private HashMap<Target, ArrayList<Node>> targetMap = new HashMap<Target, ArrayList<Node>>();
private HashMap<Cost, ArrayList<Node>> costMap = new HashMap<Cost, ArrayList<Node>>();
/** Look for a node with a given source */
for( Node node : sourceMap.get(keySource) )
{
/** Test the node for equality with a given node. Equals method below */
if(node.equals(nodeYouAreLookingFor) { return node; }
}
In order to be sure that your code will work, be sure to overwrite the equals method. I know I have said so already but this is a very common mistake.
#Override
public boolean equals(Object object)
{
if(object instanceof Node)
{
Node node = (Node) object;
if(source.equals(node.getSource() && target.equals(node.getTarget()))
{
return true;
}
} else {
return false;
}
}
If you don't, the test will simply compare references which may or may not be equal depending on how you handle your objects.
Edit: Just read what you base your equality upon. The equals method should be implemented in your node class. However, for it to work, you need to implement and override the equals method for the source and target too. That is, if they are objects. Be watchful though, if they are Nodes too, this may result in quite some tests spanning all of the network.
Update: Added code to reflect the purpose of the code in the comments.
ArrayList<Node> matchingNodes = sourceMap.get(desiredSourde).retainAll(targetMap.get(desiredTarget));
Now you have a list of all nodes that match the source and target criteria. Provided that you are willing to sacrifice a bit of memory, the lookup above will have a complexity of O(|sourceMap| * (|sourceMap|+|targetMap|)) [1]. While this is superior to just a linear lookup of all nodes, O(|allNodeList|), if your network is big enough, which with 1000 nodes I think it is, you could benefit much. If your network follows a naturally occurring network, then, as Albert-László Barabási has shown, it is likely scale-free. This means that splitting your network into lists of at least source and target will likely (I have no proof for this) result in a scale-free size distribution of these lists. Therefore, I believe the complexity of looking up source and target will be substantially reduced as |sourceMap| and |targetMap| should be substantially lower than |allNodeList|.
You'll need to combine the source and target into a single comparator, e.g.
compare(T o1, T o2) {
if(o1.source < o2.source) { return -1; }
else if(o1.source > o2.source) { return 1; }
// else o1.source == o2.source
else if(o1.target < o2.target) { return -1; }
else if(o1.target > o2.target) { return 1; }
else return 0;
}
You can use the .compareTo() method to compares your nodes.
You can create two ArrayLists. The first sorted by source, the second sorted by target.
Then you can search by source or target using binarySearch on the corresponding List.
You can make a helper class to store source-target pairs:
class SourceTarget {
public final Source source; // public fields are OK when they're final and immutable.
public final Target target; // you can use getters but I'm lazy
// (don't give this object setters. Map keys should ideally be immutable)
public SourceTarget( Source s, Target t ){
source = s;
target = t;
}
#Override
public boolean equals( Object other ){
// Implement in the obvious way (only equal when both source and target are equal
}
#Override
public int hashCode(){
// Implement consistently with equals
}
}
Then store your things in a HashMap<SourceTarget, List<Node>>, with each source-target pair mapped to the list of nodes that have exactly that source-target pair.
To retrieve just use
List<Node> results = map.get( new SourceTarget( node.source, node.target ) );
Alternatively to making a helper class, you can use the comparator in Zim-Zam's answer and a TreeMap<Node,List<Node>> with a representative Node object acting as the SourceTarget pair.

how to reorder a list of objects?

Firstly, this is going to sound like homework, but it ain't. Just a problem I'm trying to solve at work.
I have a list of objects, the objects have a sequence number which indicates their order in the list in the UI. Example:
public class Task {
Long id;
String name;
Long seq;
}
The table in my UI has "up" and "down" links on each row of the table for moving the tasks up and down in the list.
I'm implementing two methods to handle the reordering. These methods are call by ajax in the web UI.
public void incTaskSeq(List<Task> allTasks, Task taskToMove)
For example; if I have t1.seq=1, t2.seq=2, t3.seq=3, t4.seq=4, t5.seq=5 and I want to increment the place of t3, then t3.seq becomes 4, and t4.seq must become 3.
public void decTaskSeq(List<Task> allTasks, Task taskToMove)
Similarly; if I have t1.seq=1, t2.seq=2, t4.seq=3, t3.seq=4, t5.seq=5 and I want to decrement the place of t4, then t4.seq becomes 2, and t2.seq must become 3. Resulting in:
t1.seq=1, t4.seq=2, t2.seq=3, t3.seq=4, t5.seq=5
I'm a little stuck on the best way to do this.
I was thinking of putting all the tasks in a HashMap and then sort the map by the sequence number. Then locate the taskToMove in the map, change the sequence number, and then change all the affected tasks sequences.
But this approach seems inelegant. Does anyone have any ideas how I should do this?
Thanks, Rob
Use a Comparator, which is the Java interface for sorting non-naturally.
public TaskSequenceComparator implements Comparator<Task> {
public int compare(Task one, Task two) {
return one.getSequence() - two.getSequence();
}
}
...
List<Task> tasks = ...;
Collections.sort(tasks, new TaskSquenceComaprator());
// tasks is now sorted by sequence.
You can create multiple Comparator classes to implement each kind of supported sort. Then you can select from them when you need the list sorted in a particular manner.
Implement a Comparator for each criteria you want to sort for.
Create a new ordered Collection object (maybe a TreeSet) passing it the Comparator needed. Do .addAll of the objects.
Just let the List keep tarck of ordering. (Except You always need to update the seqence number).
public void incTaskSeq(List<Task> allTasks, Task taskToMove){
int movTaskNum = 0;
for(int i=0;i<allTasks.size();i++){
if(allTasks.get(i).equals(taskToMove))
movTaskNum = i;
}
allTasks.remove(taskToMove);
allTasks.add(i-1, taskToMove);
}
sorry for typos
Use a doubly linked list and swap the sequence numbers when you move an item.

Categories