I am working on a traveling salesman problem here and my p-queue isn't operating it is simply taking the last item added. I was wonder if anyone could help me figure out the error. here is my Node class (nodes which are added to the queue):
import java.util.*;
public class Node implements Comparable< Node >{
//level of node
int level;
//stores path of node
ArrayList< Integer > path = new ArrayList< Integer >();
//bound of node
int bound;
/** Over-rides compareTo for priority queue handling
* #return int desired sorting value
*/
public int compareTo(Node aNode)
{
if (this.bound<aNode.bound)
{
return 1;
}
if (this.bound>aNode.bound)
{
return -1;
}
else
{
return 0;
}
}
}
and here is the p-queue implementation:
PriorityQueue< Node > theQ = new PriorityQueue< Node >();
The algorithm is implemented correctly the p-queue simply is not putting the lowest bound as the head. I even reversed the the returns on the compareTo with no effect on the p-queue output (signifying to me that the queue is not sorting. I have wasted hours trying to figure it out and also asking some classmates (no-one can discern the problem) taking a shot here to see if anyone knows why the queue is acting like this..
Your code works perfectly fine for me.
What I suspect you're doing is changing the the bound value of a single object and repeatedly adding it, giving you a queue full of the same object (lots of references to it) which of course has the single (last) value you set it to.
public static void main(String[] args)
{
PriorityQueue< Node > theQ = new PriorityQueue< Node >();
Node n = new Node();
n.bound = 6;
theQ.add(n);
n = new Node();
n.bound = 9;
theQ.add(n);
n = new Node();
n.bound = 4;
theQ.add(n);
while ((n = theQ.poll()) != null)
System.out.println("Bound = " + n.bound);
}
Output:
Bound = 9
Bound = 6
Bound = 4
Make sure you are iterating through the PriorityQueue by using the methods provided by the Queue interface, ex. remove to pop an element off the top. In pseudo code:
for each element in some other collection
priorityQueue.add(element)
while priorityQueue is not empty
Set node to priorityQueue.remove()
Do stuff with node
If you are trying to iterate through a for-each loop or PriorityQueue.iterator:
The Iterator provided in method
iterator() is not guaranteed to
traverse the elements of the priority
queue in any particular order.
Alternatively, if you don't want to destroy/remove elements from your PriorityQueue to iterate in order, you could use, as the documentation suggests,
Arrays.sort(pq.toArray())
Related
I'm trying to write a program using Kahn's algorithm, sort of relating to BFS. Since the Queue and the List have exact keys being put in, is there anyways to remove the queue and make the list perform just like a queue and still return values? I was told to keep the preference for the List instead of removing the keys like what a queue does. I'm not sure how to do it though. Any suggestion is appreciated. Here's one part of my program.
private static List<Job> topologicalSortBFS(final List<Job> jobs) //Kahn's
{
final List<Job> sorted = new ArrayList<>(jobs.size());
final Map<Job, Integer> inCount = new HashMap<>(jobs.size());
final Queue<Job> queue = new ArrayDeque<>();
for (final Job j : jobs)
{
/* Associate every node with the amount of nodes it requires. */
final int in = j.inbound.size();
inCount.put(j, in);
/* If the node requires nothing, then add to queue and sorted list. */
if (in == 0)
{
sorted.add(j);
queue.add(j);
}
}
while (!queue.isEmpty())
{
final Job current = queue.poll(); // poll = pop
for (final Job neighbor : current.outbound)
{
/* Remove an outgoing connection without modifying the node. */
final int updatedIncount = inCount.get(neighbor) - 1;
inCount.put(neighbor, updatedIncount);
/* If node is now considered a leaf, its requirements were met. */
if (updatedIncount == 0)
{
sorted.add(neighbor);
queue.add(neighbor);
}
}
}
return sorted;
}
In your given code, only the poll( ) method is not available for the List object. However, poll( ) works in FIFO manner, returning and removing the topmost object from the queue. Alternatively, for a List you can get the first element using the get(index) method with index value 0 and also remove it. But you should consider using a LinkedList as for the remove( ) operation all the elements in ArrayList will be shifted for each removal, which is a costly operation. Also, LinkedList has the poll( ) method as it implements the Queue interface.
NOTE: Queue fits best for the given example, my answer is just a workaround to used a List as per your question.
I have a problem in which I have to search for the maximum element in a stack. I've created my own stack class and used the following approach:
Node node = top; //created a new node which points to the top of stack
int max = node.data; //max contains the value of the top node
while(node != null) {
if(node.data > max) {
max = node.data;
}
node = node.next;
}
//Print the value of max.
Can anybody suggest a more efficient way to do this?
Maintain two stack :
consist of all Nodes.
always keep Max node at top of it, which makes it easier to get max element every time.
The code goes like this :
import java.util.Stack;
public class StackWithMax extends Stack<Integer> {
Stack<Integer> s2;
public StackWithMax() {
s2 = new Stack<Integer>();
}
public void push(int value){
if (value >= max()) {
s2.push(value);
}
super.push(value);
}
public Integer pop() {
int value = super.pop();
if (value == max()) {
s2.pop();
}
return value;
}
public int max() {
if (s2.isEmpty()) {
return Integer.MIN_VALUE;
} else {
return s2.peek();
}
}
}
If you are fine with using an extra space, we can do getMax() in O(1) time. The idea is to use a PriorityQueue based on a comparator that returns the maximum of two elements. Your PriorityQueue will consist of elements arranged ina sorted way based on your comparator. Anytime you push an element in your stack, you push the maximum element corresponding to that element in the PriorityQueue as well. Lets take an example:
Suppose in your stack you are pushing the element 3. Then in your priorityQueue pQ, you would offer 3. At this time, 3 will be the max element corresponding to 3 in the stack.
Lets insert 5 in stack S. Offer 5 in pQ. Since 5 > 3, order of elements in pQ will be 5 3.
Lets push 4 in S. Offer 4 in pQ as well. pQ will now contain elements: 5 4 3. If you do getMax(), you get head of pQ which takes O(1) time since maximum element is always at top of pQ.
In case of S.pop(), you can remove the corresponding popped element from pQ as well in O(1) time if you store the pQ in the form of LinkedList. Hence, all these operations would take O(1) time really.
Going by same logic, you can also do popMax() too in O(1) time. Just return the head of pQ and delete the corresponding node from Stack as well, which again can be done in O(1) of time.
Here is how the structure of both can be:
public class Node{
int data;
Node next;
Node(int data){
this.data = data;
next = null;
}
}
PriorityQueue<Node> pQ = new PriorityQueue<Node>();
Stack<Node> S = new Stack<Node>();
This question already has answers here:
Java Priority Queue reordering when editing elements
(7 answers)
Closed 5 years ago.
I'm trying to implement Dijkstra algorithm on my own in java. I have a min-priority queue that stores nodes ordered by their current shortest path.
The first step goes smoothly, I set starting node with distance 0 and others with Integer.MAX_VALUE. The starting node was polled out correctly. However, after i removed the first node, the second node that been removed is not the node with smallest distance. I cant figure out why. Any opinions?
Here is my code
public void Dijkstra(Node s){
initialize(s);
List<Node> set = new ArrayList<Node>();
Comparator<Node> c = new CompareNode();
PriorityQueue<Node> Q = new PriorityQueue<Node>(V,c);
for (Node q: Nodes){
Q.add(q);
}
while (Q.size()!=0){
Node u = Q.remove();
System.out.println();
System.out.println(u + " is removed with dis " + u.getD());
set.add(u);
for (Node w: u.getWeightedAdj().keySet()){
relax(u,w);
}
}
}
public void initialize(Node s){
for (Node v: Nodes){
v.setD(Integer.MAX_VALUE);
v.setPredecessor(null);
}
s.setD(0);
}
public void relax(Node u, Node w){
if (w.getD()>u.getD()+u.getWeightedAdj().get(w)){
w.setD(u.getD()+u.getWeightedAdj().get(w));
w.setPredecessor(u);
}
}
And comparator class
import java.util.Comparator;
public class CompareNode implements Comparator<Node> {
#Override
public int compare(Node o1, Node o2) {
if (o1.getD()>o2.getD())
return 1;
if (o1.getD()<o2.getD())
return -1;
return 0;
}
}
when I ran it, the outcome looks like this
A is removed with dis 0
E is removed with dis 2147483647
C is removed with dis 2
D is removed with dis -2147483648
B is removed with dis 3
The problem is that the PriorityQueue orders the elements when they are added with the assumption that the order cannot change.
In your example all your distances are MaxInt when the nodes are added to the queue (except for the start node), and so they are placed into the queue in effectively a random order.
You then adjust the distances, but the PriorityQueue does not know about these adjustments so continues to return the elements in the original order.
The standard approach to this is to insert elements in the priority queue when the distance changes. (When an element is removed from the queue, you need to test whether you have already visited this element because the same element can appear multiple times in the queue.)
It would be easier to add the nodes to the queue as they get discovered. I.e. in the beginning only add the root node, and then in each iteration add the newly discovered nodes that haven't been processed. In the iteration step you need to check if new nodes are in the queue or not and possibly update them if the new distance is shorter.
I have a graph which stores it's edges using a HashMap as follows :
HashMap<Integer,LinkedList<Node>> adj;
where Node is defined ;
class Node
{
int number;
int weight;
}
eg
0 : <1,55> -> <2,54> //node 0 is connected to node 1 with edge weight 55 and node 2 with edge weight 54
1 : <0,43> -> <2,44> //node 1 is connected to node 0 with edge weight 43 and node 2 with
edge weight 44
I need to get a list of edges in sorted order by weight and I have no clue how to go about it. I am trying to implement Kruskal's MST.
Is it possible to sort the graph I have defined? If not please suggest a better way of storing it.
Let's start by creating an Edge class:
class Edge implements Comparable<Edge> { // Important: must implement Comparable. More on this later
public Node first; // first connected node
public Node second; // second connected node
public int weight; // move edge weight to Edge class
#Override
public int compareTo(Edge e) {
if (weight < e.weight) {
return -1;
} else if (weight > e.weight) {
return 1;
} else {
return 0;
}
}
}
Because the weight variable is in the Edge class, it isn't needed in Node, so you can remove it:
class Node {
public int number;
// add more variables later is you need here
}
Now, for your program (if there isn't a requirement against it), I would define your list like this:
HashMap<Node, List<Edge>> adj; // use any list implementation you want
This will represent the graph like this inside your program (copied from your example):
Node 0: Edge(Node 0, Node 1, 55), Edge(Node 0, Node 2, 54)
Node 1: Edge(Node 1, Node 0, 43), Edge(Node 1, Node 2, 44)
To answer your question, lets find the edges sorted by edge weight:
ArrayList<Edge> sortedEdges = new ArrayList<Edge>();
for (List<Edge> connectedEdges : adj.values()) {
sortedEdges.addAll(connectedEdges);
}
Collections.sort(sortedEdges);
This simply takes all the Edges in adj and puts them all in one list, and then sorts them according to their weight (because we made Edge extend Comparable<Edge>). As per the Javadoc on Collections.sort(), the sort() method uses merge sort, which runs in O(nlog(n)) time:
Implementation note: This implementation is a stable, adaptive, iterative mergesort that requires far fewer than n lg(n) comparisons when the input array is partially sorted, while offering the performance of a traditional mergesort when the input array is randomly ordered.
Getting the list of all Edges by adj.values takes O(n) time (see this), so the total time complexity of getting the list of edges sorted by weight will be O(n) + O(nlog(n)) = O(nlog(n)).
So there you go. I hope this helped :)
If you have the freedom to change the way nodes are represented, I would like to suggest changing it. Currently the Node class really represents an edge (and a node is represented by Integer, i.e., keys to the adj variable.
For example, the following seems more natural:
Set<Node> nodes = new HashSet<>(); // The enclosing class keeps track of all nodes.
// Represents each node.
class Node {
int nodeId = /* ... */;
// The Node class keeps track of its neighbors, sorted by their weights.
SortedMap<Integer,Node> edges = new TreeMap<>(Collections.reverseOrder());
}
Then, whenever you need to do things in the descending order of the weight, you could do something like:
void method(Node node) {
Iterator<Integer> iter = node.edges.keySet().iterator(); // Iterates in descending order.
while(iter.hasNext()) {
int weight = iter.next();
Node neighbor = node.edges.get(weight);
doSomething( /* ... */ );
}
}
I am trying to create a bubble sort on a doubly linked linked list in Java but am getting Null Pointer Exception errors. I believe it to have an issue with when I call the getPrevious method on the head which of course has a value of null. However, I cannot think how to do the bubble sort without accessing the getPrevious method for the other nodes.
I can implement an if statement to check if its the head or tail of the list first, but I feel like there is a smarter way to do this.
I also have been unable to run a successful build of this, so am not even sure the code will work. If you have a different idea of how to implement this please let me know.
Any suggestions are welcome!
public static void bubbleSort(DoubleLinkedList list) //static method used to sort the linked list using bubble sort
{
int i = 0;
int j = 0;
Node currentNode = list.head;
Node previousNode = currentNode;
Node tempNext = currentNode;
Node tempPrevious = currentNode;
for(i=0; i<list.getSize(); i++)
{
for(j=0; j<list.getSize()-1; i++)
{
if(currentNode.getData() > currentNode.getNext().getData())
{
tempNext = currentNode.getNext().getNext();
tempPrevious = currentNode.getPrevious();
currentNode.getPrevious().setNext(currentNode.getNext());
currentNode.getNext().setNext(currentNode);
currentNode.setPrevious(currentNode.getNext());
currentNode.setNext(tempNext);
}
currentNode = currentNode.getNext();
}
}
}
So you have a double linked list. I assume each element contains some information... say an integer. It must also contain two pointers: one to the previous element and one to the next element.
Assuming this is true, notice that you don't have to modify the pointers because they already point from one element to another. all you have to do is sort the values of the list elements so that the first item in the list has the lowest value, the second has the second lowest value and so on.
You can do it like this:
public static void bubbleSort(DoubleLinkedList list) //static method used to sort the linked list using bubble sort {
int i = 0;
Node currentNode = list.head;
Node auxNode;
int foundChange = 1;
while(foundChange) {
foundChange = 0;
for(i=0; i<list.getSize()-1; i++) {
if (currentNode.getData() > currentNode.getNext().getData()) {
auxNode.setData(currentNode.getData());
currentNode.setData(currentNode.getNext.getData());
currentNode.getNext.setData(auxNode.getData());
foundChange = 1;
}
currentNode = currentNode.getNext();
}
}
If you haven't defined the setData method yet, then do so. It must be similar to getData, but it will set the data of an object to the value it gets as a parameter instead of returning the value of the data in that object.