I have a Priority Queue in which I add a Node object to, where the Nodes should be sorted by a value that they contain. For some reason, the priority queue will not sort the Nodes on add. If anyone can see something wrong with this or has any guidance, I appreciate it. Here is a brief example:
PriorityQueue<Node> PQ = new PriorityQueue<Node>();
//for each entry create a node and add it to the PriorityQueue
for(Entry<Character,Integer> entry : entries){
PQ.add(new Node(entry.getKey(),entry.getValue(), true));
}
here is the node's compareTo method:
#Override
public int compareTo(Node n) {
if(n.frequency.intValue() > this.frequency.intValue()) return -1;
else if(n.frequency.intValue() == this.frequency.intValue()) return 0;
else return 1;
}
I guess you expect PriorityQueue to return elements in particular order when you iterate it. However, PriorityQueue doesn't provide such a behaviour, because it's implemented as a priority heap rather than sorted list. From javadoc:
The Iterator provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).
The only guarantee provided by PriorityQueue is that poll(), peek(), etc return the least element. If you need ordered iteration of elements, use some other collection such as TreeSet.
For anyone looking how to iterate the queue following the order, this can be achieved by using poll or remove.
while (!queue.isEmpty())
System.out.println(queue.poll());
while (!queue.isEmpty())
System.out.println(queue.remove());
The only diference between poll() and remove(), is that poll returns null when is empty and remove throws a NoSuchElementException.
Related
So I have tried to make an insertion sort for doubly linked list with iterators. It returns a sorted list with the 'keys' sorted from smaller to bigger. Althought my code doesn't sort the actual list and i am not sure if it's an insertion sort. Can anyone help?
public static List sort(List list) {
List sortedList = new List(); // sortedList
List.Iter curIndex = List.Iter.last(sortedList); // terminated forward iterator
for(List.Iter iter = List.Iter.first(list); !iter.end(); iter.next()) {
curIndex = List.Iter.last(sortedList);
List.Node node = iter.key_data();
System.out.println("node: "+node.data);
System.out.println("curIndex: "+curIndex.key_data().data);
if (sortedList.empty()) {
sortedList.insAfter(curIndex, node.key, node.data);
}
else if (curIndex.key_data().key >= node.key) {
boolean hasPrev = true;
while (hasPrev && curIndex.key_data().key >= node.key) {
hasPrev = curIndex.prev();
}
sortedList.insAfter(curIndex, node.key, node.data);
}
else {
boolean hasNext = true;
while (hasNext && curIndex.key_data().key < node.key) {
hasNext = curIndex.next();
}
sortedList.insAfter(curIndex, node.key, node.data);
}
}
return sortedList;
}
Whether or not the definition of insertion sort would still consider your code to be an implementation of that, is probably a matter of interpretation. But in the more strict definition of insertion sort, the algorithm should move nodes, not create new nodes. This is what Wikipedia has as definition:
Insertion sort iterates, consuming one input element each repetition, and grows a sorted output list. At each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there.
I highlight the word removes, which is an action your algorithm does not perform. The same article has a section specifically on linked lists, where it states (my highlights):
If the items are stored in a linked list, then the list can be sorted with O(1) additional space. The algorithm starts with an initially empty (and therefore trivially sorted) list. The input items are taken off the list one at a time, and then inserted in the proper place in the sorted list. When the input list is empty, the sorted list has the desired result.
Your implementation needs O(n) space. It would be more in line with the spirit of insertion sort, if it would do as described in that quote: instead of creating new nodes, it could take the original node object out of the original list, and rewire it so it becomes part of the newly sorted list, such that the whole process does not ever create new nodes.
I have a Priority Queue in which I add a Node object to, where the Nodes should be sorted by a value that they contain. For some reason, the priority queue will not sort the Nodes on add. If anyone can see something wrong with this or has any guidance, I appreciate it. Here is a brief example:
PriorityQueue<Node> PQ = new PriorityQueue<Node>();
//for each entry create a node and add it to the PriorityQueue
for(Entry<Character,Integer> entry : entries){
PQ.add(new Node(entry.getKey(),entry.getValue(), true));
}
here is the node's compareTo method:
#Override
public int compareTo(Node n) {
if(n.frequency.intValue() > this.frequency.intValue()) return -1;
else if(n.frequency.intValue() == this.frequency.intValue()) return 0;
else return 1;
}
I guess you expect PriorityQueue to return elements in particular order when you iterate it. However, PriorityQueue doesn't provide such a behaviour, because it's implemented as a priority heap rather than sorted list. From javadoc:
The Iterator provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).
The only guarantee provided by PriorityQueue is that poll(), peek(), etc return the least element. If you need ordered iteration of elements, use some other collection such as TreeSet.
For anyone looking how to iterate the queue following the order, this can be achieved by using poll or remove.
while (!queue.isEmpty())
System.out.println(queue.poll());
while (!queue.isEmpty())
System.out.println(queue.remove());
The only diference between poll() and remove(), is that poll returns null when is empty and remove throws a NoSuchElementException.
I am trying to merge multiple sorted lists into one TreeSet.. And then I am thinking to apply Binary Search algorithm on that TreeSet to retrieve the element in O(log n) time complexity..
Below is my code in which I am passing List of Lists in in one of my method and combining them into TreeSet to avoid duplicacy... All the lists inside inputs are sorted -
private TreeSet<Integer> tree = new TreeSet<Integer>();
public void mergeMultipleLists(final List<List<Integer>> inputs) {
tree = new TreeSet<Integer>();
for (List<Integer> input : inputs) {
for(Integer ii : input) {
tree.add(ii);
}
}
}
public List<Integer> getItem(final Integer x) {
// extract elements from TreeSet in O(log n)
}
First of all, is this right way to merge multiple sorted lists into TreeSet? Is there any direct way to merge multiple sorted lists in TreeSet efficiently?
Secondly, how would I extract an element from that TreeSet in O(log n) time complexity? I would like to find an element x in that TreeSet, if it is there, then return it, if it is not there then return the next largest value from the TreeSet.
Or may be I am better off to another data structure as compared to which I am using currently?
UPDATED CODE:-
private TreeSet tree = new TreeSet();
public SearchItem(final List<List<Integer>> inputs) {
tree = new TreeSet<Integer>();
for (List<Integer> input : inputs) {
tree.addAll(input);
}
}
public Integer getItem(final Integer x) {
if(tree.contains(x)) {
return x;
} else {
// now how do I extract next largest
// element from it if x is not present
}
}
TreeSet is backed by a NavigableMap, a TreeMap specifically. Calling contains() on a TreeSet delegates to TreeMap.containsKey(), which is a binary search implementation.
You can check if an object is contained in the set by using TreeSet.contains(), but you have to have the object first. If you want to be able to look up and retrieve an object, then a Map implementation will be better.
You could use TreeSet.floor(), which according to the docs
Returns the greatest element in this set less than or equal to the given element, or null if there is no such element.
TreeSet, by it's nature is a sorted set and uses a red-tree-black-tree via TreeMap as it's backing
Basically: TreeSet.add(E) -> TreeMap.put(E,NULL);
As it is already a binary, sorted tree structure any 'get' or 'contains' will result in an O(log n) operation.
Your code and your question though don't line up.
You're flattening a List<List<Integer>> and just putting them all in to get all unique elements (or, at least, that's what this code will do).
But then your following method says "given this integer, give me a List<Integer>" which isn't achievable in the above code
So, let me answer your questions in order:
Sure/Yes Y
No. You misunderstand Sets (you can't extract by design) If you can do Set.contains(e)
then you HAVE the element and need not extract anything
If you need to do something like a "Set extraction" then use a TreeMap or turn your set back into a list and do myList.get(Collections.binarySearch(myElement));
I have a Priority Queue in which I add a Node object to, where the Nodes should be sorted by a value that they contain. For some reason, the priority queue will not sort the Nodes on add. If anyone can see something wrong with this or has any guidance, I appreciate it. Here is a brief example:
PriorityQueue<Node> PQ = new PriorityQueue<Node>();
//for each entry create a node and add it to the PriorityQueue
for(Entry<Character,Integer> entry : entries){
PQ.add(new Node(entry.getKey(),entry.getValue(), true));
}
here is the node's compareTo method:
#Override
public int compareTo(Node n) {
if(n.frequency.intValue() > this.frequency.intValue()) return -1;
else if(n.frequency.intValue() == this.frequency.intValue()) return 0;
else return 1;
}
I guess you expect PriorityQueue to return elements in particular order when you iterate it. However, PriorityQueue doesn't provide such a behaviour, because it's implemented as a priority heap rather than sorted list. From javadoc:
The Iterator provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).
The only guarantee provided by PriorityQueue is that poll(), peek(), etc return the least element. If you need ordered iteration of elements, use some other collection such as TreeSet.
For anyone looking how to iterate the queue following the order, this can be achieved by using poll or remove.
while (!queue.isEmpty())
System.out.println(queue.poll());
while (!queue.isEmpty())
System.out.println(queue.remove());
The only diference between poll() and remove(), is that poll returns null when is empty and remove throws a NoSuchElementException.
if I use a for-each loop on a linked list in java,
is it guaranteed that I will iterate on the elements in the order
in which they appear in the list?
I found 5 main ways to iterate over a Linked List in Java (including the Java 8 way):
For Loop
Enhanced For Loop
While Loop
Iterator
Collections’s stream() util (Java8)
For loop
LinkedList<String> linkedList = new LinkedList<>();
System.out.println("==> For Loop Example.");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
Enhanced for loop
for (String temp : linkedList) {
System.out.println(temp);
}
While loop
int i = 0;
while (i < linkedList.size()) {
System.out.println(linkedList.get(i));
i++;
}
Iterator
Iterator<String> iterator = linkedList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
collection stream() util (Java 8)
linkedList.forEach((temp) -> {
System.out.println(temp);
});
One thing should be pointed out is that the running time of For Loop or While Loop is O(n square) because get(i) operation takes O(n) time(see this for details). The other 3 ways take linear time and performs better.
Linked list is guaranteed to act in sequential order.
From the documentation
An ordered collection (also known as a
sequence). The user of this interface
has precise control over where in the
list each element is inserted. The
user can access elements by their
integer index (position in the list),
and search for elements in the list.
iterator()
Returns an iterator over the elements in this list in proper sequence.
As the definition of Linkedlist says, it is a sequence and you are guaranteed to get the elements in order.
eg:
import java.util.LinkedList;
public class ForEachDemonstrater {
public static void main(String args[]) {
LinkedList<Character> pl = new LinkedList<Character>();
pl.add('j');
pl.add('a');
pl.add('v');
pl.add('a');
for (char s : pl)
System.out.print(s+"->");
}
}
Linked list does guarantee sequential order.
Don't use linkedList.get(i), especially inside a sequential loop since it defeats the purpose of having a linked list and will be inefficient code.
Use ListIterator
ListIterator<Object> iterator = myLinkedList.listIterator();
while( iterator.hasNext()) {
System.out.println(iterator.next());
}
Each java.util.List implementation is required to preserve the order so either you are using ArrayList, LinkedList, Vector, etc. each of them are ordered collections and each of them preserve the order of insertion (see http://download.oracle.com/javase/1.4.2/docs/api/java/util/List.html)
Adding my inputs for future visitors.
First things first: as per $jls-14.14.2, for-each internally use Iterator.
Now, when you iterate over LinkedList using a for-each or an iterator then the looping is always sequential.
But this is prone to thread safety issues. So, two things can happen:
If you use a non-threadsafe List implementation then you will run into ConcurrentModificationException
You can use a threadsafe List implementation like CopyOnWriteArrayList. And if you must use a LinkedList only then use Collections.synchronizedList() to convert your non-threadsafe LL into a threadsafe LL, but again you need to watch out for using iterator in a threadsafe manner.