Background
I am trying to code Dijkstra's algorithm in O(mlogn) time, where m is the number of edges and n is the number of nodes. I am using to find the shortest path between a given starting node and a given ending node. And I'm pretty new at this.
Here is the algorithm I have come up with:
Assume the graph is represented by an adjacency matrix and each node has a row index.
Initialize starting node distance to zero, and all other nodes to inifinity, in the heap.
Create a list of shortest paths, equal to the number of nodes in the graph, set to 0.
While the index of the node that corresponds to the minimum element in the heap
has no value in the list of shortest paths and heap has node distances, do:
Remove the minimum node distance from the heap, and bubble as necessary to fill the removed node.
Put the minimum node distance into the list of shortest paths at its row index.
For all nodes that were adjacent to the node with the minimum distance (that was just removed), do:
Update the distances in the heap for the current node, using the following calculation:
min((deleted node distance + adjacent edge weight), current node's distance)
Reorganize the heap to be a minimum heap.
Return value in the list of shortest paths at the location of the end node.
This is O(mlogn) because you only update the distances once per edge.
"It takes linear time
to initialize the heap, and then we perform m updates at a cost of O(log n) each for a total time of O(mlog n)." - http://www.cs.cmu.edu/~avrim/451f07/lectures/lect1011.pdf
Problem
In order to update the distances from the starting vertex in the correct location in the heap, insertions to the heap must be key-value pairs - with the key being the node (row index) and the value being the distance.
There are lecture slides online that say each entry in a priority queue ADT is a key-value pair (otherwise, how could it prioritize?).
Question
The methods for PriorityQueue have at most one parameter, so how do you insert a key associated with a value?
This must be done in a single file with a specific name (i.e. It is my understanding that I can't make a KeyValuePair class implementing Comparator).
I'd love to hear your thoughts.
To use JDK's implementation of priority queue for your application, you can maintain a Map<Key, Value> in addition to PriorityQueue<Value>. In your case, Key represents a node and Value is an object that holds the shortest distance to a node. To update the distance to a node, you first look up its corresponding distance object in the map. Then, you remove the distance object from the priority queue. Next, you update the distance object. Finally, you insert the distance object back in the priority queue.
Below is the Dijkstra implementation using priority_queue .
Here ignore the InputReader class as it is for fast input . We can maintain priority according to "Value" of pair in key value pair . Then choose the Pair with minimum cost i.e value .
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.List;
import java.util.PriorityQueue;
/**
* By: Rajan Parmar
* At : HackerRank
**/
public class Dijkstra {
// node ,pair ( neighbor , cost)
static HashMap < Integer , HashSet <Pair>> node;
static PrintWriter w;
public static void main(String [] s) throws Exception{
InputReader in;
boolean online = false;
String fileName = "input";
node = new HashMap<Integer, HashSet<Pair>>();
//ignore online if false it is for online competition
if (online) {
//ignore
in = new InputReader(new FileInputStream(
new File(fileName + ".txt")));
w = new PrintWriter(new FileWriter(fileName + "Output.txt"));
} else {
// for fast input output . You can use any input method
in = new InputReader(System.in);
w = new PrintWriter(System.out);
}
// Actual code starts here
int t;
int n, m;
t = in.nextInt();
while(t-- > 0){
n = in.nextInt();
m = in.nextInt();
while(m-- > 0){
int x,y,cost;
x = in.nextInt();
y = in.nextInt();
cost = in.nextInt();
if(node.get(x)==null){
node.put(x, new HashSet());
node.get(x).add(new Pair(y,cost));
}
else{
node.get(x).add(new Pair(y,cost));
}
if(node.get(y)==null){
node.put(y, new HashSet());
node.get(y).add(new Pair(x,cost));
}
else{
node.get(y).add(new Pair(x,cost));
}
}
int source = in.nextInt();
Dijkstra(source,n);
node.clear();
System.out.println("");
}
}
static void Dijkstra(int start , int n) {
int dist[] = new int[3001];
int visited[] = new int[3001];
Arrays.fill(dist, Integer.MAX_VALUE);
Arrays.fill(visited, 0);
dist[start] = 0 ;
PriorityQueue < Pair > pq = new PriorityQueue();
//this will be prioritized according to VALUES (i.e cost in class Pair)
pq.add(new Pair(start , 0));
while(!pq.isEmpty()){
Pair pr = pq.remove();
visited[pr.neighbor] = 1;
for(Pair p:node.get(pr.neighbor)){
if(dist[p.neighbor] > dist[pr.neighbor] + p.cost){
dist[p.neighbor] = dist[pr.neighbor] + p.cost;
//add updates cost to vertex through start vertex
if(visited[p.neighbor]==0)
pq.add(new Pair(p.neighbor ,dist[p.neighbor] ));
}
}
}
for(int i=1;i<=n;i++){
if(i==start) continue;
if(visited[i]==0)
dist[i]=-1;
System.out.print(dist[i]+" ");
}
}
static class Pair implements Comparable {
int neighbor;
int cost;
public Pair(int y, int cost) {
// TODO Auto-generated constructor stub
neighbor = y;
this.cost = cost;
}
#Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Pair pr = (Pair)o;
if(cost > pr.cost)
return 1;
else
return -1;
}
}
//Ignore this class , it is for fast input.
static class InputReader {
private InputStream stream;
private byte[] buf = new byte[8192];
private int curChar, snumChars;
private SpaceCharFilter filter;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int snext() {
if (snumChars == -1)
throw new InputMismatchException();
if (curChar >= snumChars) {
curChar = 0;
try {
snumChars = stream.read(buf);
} catch (IOException e) {
throw new InputMismatchException();
}
if (snumChars <= 0)
return -1;
}
return buf[curChar++];
}
public int nextInt() {
int c = snext();
while (isSpaceChar(c))
c = snext();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = snext();
}
int res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = snext();
} while (!isSpaceChar(c));
return res * sgn;
}
public long nextLong() {
int c = snext();
while (isSpaceChar(c))
c = snext();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = snext();
}
long res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = snext();
} while (!isSpaceChar(c));
return res * sgn;
}
public int[] nextIntArray(int n) {
int a[] = new int[n];
for (int i = 0; i < n; i++)
a[i] = nextInt();
return a;
}
public String readString() {
int c = snext();
while (isSpaceChar(c))
c = snext();
StringBuilder res = new StringBuilder();
do {
res.appendCodePoint(c);
c = snext();
} while (!isSpaceChar(c));
return res.toString();
}
public boolean isSpaceChar(int c) {
if (filter != null)
return filter.isSpaceChar(c);
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
public interface SpaceCharFilter {
public boolean isSpaceChar(int ch);
}
}
}
This will take input in following format .
First line be T (no. of test case).
For each test case next line input will be N and M , where N is no of nodes , M is no of edges.
Next M line contains 3 integers i.e x,y,W. It represents edge between node x and y with weight W.
Next line contain single integer i.e. Source node .
Output :
Print shortest distance to all node from given source node . If node is unreachable print -1.
e.g
Input :
1
6 8
1 2 1
1 5 4
2 5 2
2 3 2
5 6 5
3 6 2
3 4 1
6 4 3
1
Output : (shortest distance of all node from node 1)
1 3 4 3 5
I appreciate the answers to my question and at the time I chose the Map answer because given my limited understanding of the language, it seemed easier for me to implement.
It turns out that I overlooked an important detail that made the problem much simpler than I thought it was: if I maintain an array of distances and insert the nodes into the heap (instead of the distances), to use as references to the distance array, I was able to sort the nodes based on their values.
In this implementation, I didn't need to contrive a key-value property after all. After updating the values in the distance array, I had to remove and re-add those specific nodes to the heap in order for the heap to stay current and sorted, as suggested by #reprogrammer.
Once I changed what I was putting into the heap, the algorithm was very similar to the one found on Wikipedia.
Here is the code I ended up using, in case anyone has the same problem. Note: the magic part is the creation of the PriorityQueue (which is similar to what was suggested by #stevevls):
import java.util.*;
import java.io.File; //Because files were used to test correctness.
import java.lang.Math;
public class Dijkstra{
//This value represents infinity.
public static final int MAX_VAL = (int) Math.pow(2,30);
/* Assumptions:
If G[i][j] == 0, there is no edge between vertex i and vertex j
If G[i][j] > 1, there is an edge between i and j and the value of G[i][j] is its weight.
No entry of G will be negative.
*/
static int dijkstra(int[][] G, int i, int j){
//Get the number of vertices in G
int n = G.length;
// The 'i' parameter indicates the starting node and the 'j' parameter
// is the ending node.
//Create a list of size n of shortest paths, initialize each entry to infinity
final int[] shortestPaths = new int[n];
for(int k = 0; k < n; k++){
shortestPaths[k] = MAX_VAL;
}
//Initialize starting node distance to zero.
shortestPaths[i] = 0;
//Make a Priority Queue (a heap)
PriorityQueue<Integer> PQ = new PriorityQueue<Integer>(n,
new Comparator<Integer>()
{
public int compare(Integer p, Integer q)
{
return shortestPaths[p] - shortestPaths[q];
}
} );
//Populate the heap with the nodes of the graph
for(int k = 0; k < n; k++){
PQ.offer(k);
}
//While the heap has elements.
while(PQ.size() > 0){
// Remove the minimum node distance from the heap.
int minimum = PQ.poll();
// Check if graph is disconnected, if so, return -1.
if(shortestPaths[minimum] == MAX_VAL)
{
return -1;
}
// End node has been reached (i.e. you've found the shortest path), return the distance.
if( minimum == j){
return shortestPaths[j];
}
// Take the current node and look through the row to see the vertices adjacent to it (neighbours)
for(int columnIt = 0; columnIt < n; columnIt ++){
// Update the distances in the heap for the current node, using the following calculation:
// min((deleted node distance + adjacent edge weight), current node's distance)
if(G[minimum][columnIt] > 0){
int sum = shortestPaths[minimum] + G[minimum][columnIt];
shortestPaths[columnIt]= Math.min(sum, shortestPaths[columnIt]);
if(shortestPaths[columnIt]==sum)
{
PQ.remove(columnIt);
PQ.offer(columnIt);
}
}
}
}
return -1;
}
Thank you for your answers and advice.
I am resolving the same issue. I know where you can find the answer on you question.
It's a great book with example of code - Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
Site book and Example of code (including an implementation of Dijkstra's algorithm using a PriorityQueue)
This implementation of Dijkstra's algorithm doesn't use Java's standard PriorityQueue implementation. Instead it implements IndexMinPQ, which was discussed earlier in the book with a detailed explanation!
Related
public class Problem3 {
public static void main (String [] args){
Scanner sc= new Scanner (System.in);
System.out.println("Enter no. of Islands");
int n= sc.nextInt();
Graph g = new Graph (n);
System.out.println("Enter no. of one-way bridges");
int m= sc.nextInt();
System.out.println("Enter no. of island you want to be intially on");
int r= sc.nextInt();
try{ for (int i=0; i<m;i++){
System.out.println("This one-way bridge connects between");
int u = sc.nextInt();
int v = sc.nextInt();
if(u == v || u>n || v>n){ throw new Bounds("");}
else{ g.addEgde(u-1, v-1);}
}
g.topoSort();}
catch(IndexOutOfBoundsException e){
System.out.println("Please enter a valid input!");
}
catch(Bounds e){
System.out.println("Please enter a valid input!");
}
}
public static class Bounds extends Exception{
public Bounds (String message){
super(message);
}}
static class Graph {
int V;
LinkedList<Integer>[] adjList;
Graph(int V) {
this.V = V;
adjList = new LinkedList[V];
for (int i = 0; i < V; i++) {
adjList[i] = new LinkedList<>();
}
}
public void addEgde(int u, int v) {
adjList[u].addFirst(v);
}
public void topoSort() {
boolean[] visited = new boolean[V];
stack stack = new stack();
for (int i = 0; i < V; i++) {
if (!visited[i]) {
topoSortRE(i, visited, stack);
}
}
System.out.println("Topological Sort: ");
int size = stack.size();
for (int i = 0; i <size ; i++) {
System.out.print(stack.pop()+ 1 + " ");
}
}
public void topoSortRE(int s, boolean[] visited, stack stack) {
visited[s] = true;
for (int i = 0; i < adjList[s].size(); i++) {
int vertex = adjList[s].get(i);
if (!visited[vertex])
topoSortRE(vertex, visited, stack);
}
stack.push(s);
}}}
The following code is an attempt to solve the following problem:
There are many islands that are connected by one-way bridges, that is, if a bridge connects
islands a and b, then you can only use the bridge to go from a to b but you cannot travel back
by using the same. If you are on island a, then you select (uniformly and randomly) one of
the islands that are directly reachable from a through the one-way bridge and move to that
island. You are stuck on an island if you cannot move any further. It is guaranteed that if
there is a directed path from one island to the second there is no path that leads from the
second back to the first. In other words the formed graph is a Directed Acyclic Graph.
Find the island that you are most likely to get stuck on; that is the island that you can
possibly reach with the maximum number of paths from all other islands.
Input format:
First line: Three integers n (the number of islands), m (the number of one-way bridges), and r
(the index of the island you are initially on)
Next m lines: Two integers ui and vi representing a one-way bridge from island ui to vi.
Output format:
Print the index of the island that you are most likely to get stuck on. If there are multiple
islands, then print them in the increasing order of indices (space separated values in a single
line).
Sample input
5, 7, 1
(1, 2)
(1, 3)
(1, 4)
(1, 5)
(2, 4)
(2, 5)
(3, 4)
Sample output
4
I wrote the code to topologically sort the graph but I am having issues with how to make the input r the intial island and also how to make the output be the most probable island to be stuck on. I know that the island I'm most likely to be stuck on is the island that has the most indegrees and no outdegrees but don't know how to implement that.
For each node make a value (real number) representing probability that you will reach it from your starting island. At first, set this value for initial node to 1 and 0 for other nodes.
During the topological sort, when you're in node v, add its probability value divided by number of neighbors to each neighbor's value (in other words, since you know that the probability of getting to v is v.value, then the probability of reaching its neighbor should be increased by v.value * ppb of choosing this neighbor, that is 1 / #_of_neighbors). In this way, whenever you're in some node during topological sort, its value will be equal to the total probability of reaching it.
Your answer is an ending island (node with outdegree 0) with largest value.
Your topological sort seems wrong, you're doing something that looks like DFS. In topological sort you want to visit each vertex after visiting all vertices with an edge ending in it.
About implementation, I changed your DFS into topological sort and added those probabilities I've talked about. I left the part about choosing best ending vertex to you, I don't think doing all the work for someone is educational in any way. Also, I do not guarantee that my changes below do not contain any spelling mistakes, etc. I did my best, but I have not run this code.
static class Graph {
int V;
LinkedList<Integer>[] adjList;
Graph(int V) {
this.V = V;
adjList = new LinkedList[V];
probability = new double[V];
for (int i = 0; i < V; i++) {
adjList[i] = new LinkedList<>();
}
}
public void addEgde(int u, int v) {
adjList[u].addFirst(v);
}
public void topoSort(int start) {
double[] probability;
probability[start] = 1;
int[] indegree = new int[V];
stack stack = new stack();
for (int i = 0; i < V; i++) {
probability[i] = 0;
for (int j = 0; j < adjList[i].size(); ++j) {
indegree[adjList[i][j]] += 1;
}
}
probability[start] = 1;
for(int i = 0; i < V; ++i)
{
if(indegree[i] == 0)
stack.push(i);
}
while(stack.size())
{
int v = stack.pop();
for (int i = 0; i < adjList[v].size(); ++i)
{
indegree[adjList[v][i]] -= 1;
probability[adjList[v][i]] += probability[v] / (double)(adjList[v].size());
if(indegree[adjList[v][i]] == 0)
stack.push(adjList[v][i]);
}
}
//probability array now contains all probabilities to visit each node
}
}
}
Its an assignment task,I have spend 2 days to come up with a solution but still having lots of confusion,however here I need to make few points clear. Following is the problem:
Yuckdonald’s is considering opening a series of restaurant along QVH. n possible locations are along a straight line and the distances of these locations from the start of QVH are in miles and in increasing order m1, m2, ...., mn. The constraints are as follows:
1. At each location, Yuckdonald may open one restaurant and expected profit from opening a restaurant at location i is given as pi
2. Any two restaurants should be at least k miles apart, where k is a positive integer
My solution:
public class RestaurantProblem {
int[] Profit;
int[] P;
int[] L;
int k;
public RestaurantProblem(int[] L , int[] P, int k) {
this.L = L;
this.P = P;
this.k = k;
Profit = new int[L.length];
}
public int compute(int i){
if(i==0)
return 0;
Profit[i]= P[i]+(L[i]-L[i-1]< k ? 0:compute(i-1));//if condition satisfies then adding previous otherwise zero
if (Profit[i]<compute(i-1)){
Profit[i] = compute(i-1);
}
return Profit[i];
}
public static void main(String args[]){
int[] m = {0,5,10,15,19,25,28,29};
int[] p = {0,10,4,61,21,13,19,15};
int k = 5;
RestaurantProblem rp = new RestaurantProblem(m, p ,k);
rp.compute(m.length-1);
for(int n : rp.Profit)
System.out.println(n);
}
}
This solution giving me 88 however if I exclude (Restaurant at 25 with Profit 13) and include (Restaurant 28 with profit 19) I can have 94 max...
point me if I am wrong or how can I achieve this if its true.
I was able to identify 2 mistakes:
You are not actually using dynamic programming
, you are just storing the results in a data structure, which wouldn't be that bad for performance if the program worked the way you have written it and if you did only 1 recursive call.
However you do at least 2 recursive calls. Therefore the program runs in Ω(2^n) instead of O(n).
Dynamic programming usually works like this (pseudocode):
calculate(input) {
if (value already calculated for input)
return previously calculated value
else
calculate and store value for input and return result
}
You could do this by initializing the array elements to -1 (or 0 if all profits are positive):
Profit = new int[L.length];
Arrays.fill(Profit, -1); // no need to do this, if you are using 0
public int compute(int i) {
if (Profit[i] >= 0) { // modify the check, if you're using 0 for non-calculated values
// reuse already calculated value
return Profit[i];
}
...
You assume the previous restaurant can only be build at the previous position
Profit[i] = P[i] + (L[i]-L[i-1]< k ? 0 : compute(i-1));
^
Just ignores all positions before i-1
Instead you should use the profit for the last position that is at least k miles away.
Example
k = 3
L 1 2 3 ... 100
P 5 5 5 ... 5
here L[i] - L[i-1] < k is true for all i and therefore the result will just be P[99] = 5 but it should be 34 * 5 = 170.
int[] lastPos;
public RestaurantProblem(int[] L, int[] P, int k) {
this.L = L;
this.P = P;
this.k = k;
Profit = new int[L.length];
lastPos = new int[L.length];
Arrays.fill(lastPos, -2);
Arrays.fill(Profit, -1);
}
public int computeLastPos(int i) {
if (i < 0) {
return -1;
}
if (lastPos[i] >= -1) {
return lastPos[i];
}
int max = L[i] - k;
int lastLastPos = computeLastPos(i - 1), temp;
while ((temp = lastLastPos + 1) < i && L[temp] <= max) {
lastLastPos++;
}
return lastPos[i] = lastLastPos;
}
public int compute(int i) {
if (i < 0) {
// no restaurants can be build before pos 0
return 0;
}
if (Profit[i] >= 0) { // modify the check, if you're using 0 for non-calculated values
// reuse already calculated value
return Profit[i];
}
int profitNoRestaurant = compute(i - 1);
if (P[i] <= 0) {
// no profit can be gained by building this restaurant
return Profit[i] = profitNoRestaurant;
}
return Profit[i] = Math.max(profitNoRestaurant, P[i] + compute(computeLastPos(i)));
}
To my understanding, the prolem can be modelled with a two-dimensional state space, which I don't find in the presented implementation. For each (i,j) in{0,...,n-1}times{0,...,n-1}` let
profit(i,j) := the maximum profit attainable for selecting locations
from {0,...,i} where the farthest location selected is
no further than at position j
(or minus infinity if no such solution exist)
and note that the recurrence relation
profit(i,j) = min{ p[i] + profit(i-1,lastpos(i)),
profit(i-1,j)
}
where lastpos(i) is the location which is farthest from the start, but no closer than k to position i; the first case above corresponds to selection location i into the solution while the second case corresponds to omitting location j in the solution. The overall solution can be obtained by evaluating profit(n-1,n-1); the evaluation can be done either recursively or by filling a two-dimensional array in a bottom-up manner and returning its contents at (n-1,n-1).
Here is the question I am trying to answer
Construct a new sorting algorithm which uses ONLY three stacks, labelled A, B, and C, a
single “double” variable called x, and any auxiliary variables such as loop counters. Your
algorithm assumes that stack A contains a collection of UNSORTED data, and by the end
of your algorithm, one of the stacks will contain the data sorted in increasing order.
I am trying to figure out the algorithm for it in Java, but I can't figure it out for the life of me! Can you help?!
If there's a bonus for doing a faster sort, with 3 stacks you can implement a bottom up merge sort O(n log(n)). As pointed out by greybeard, a poly phase bottom up merge sort (a method oriented towards tape drives or other sequential devices), should be the fastest 3 stack sort.
A simpler merge sort would move every run (initial size == 1) from A to B and C, in an alternating pattern, even runs to B, odd runs to C, then 2 way merge B and C back to A, double run size, repeat until run size >= stack size. Poly phase eliminates the move / split steps, except for an initial distribute step that moves some of the elements from A to B and C.
Setting up the initial descending / ascending state (reverses the sense of a compare), and tracking when the run size on a stack changes (+1 or -1) due to dummy elements was a bit tricky. I used a table of 47 Fibonacci integers for initial distribution setup (handles stack size up to 1/2 billion elements). Stack size is known at the start, but this could be generated by doing a single copy (copy order doesn't matter since initial run size is 1).
Initial distribution for n elements: Assume that fib(m+1) > n > fib(m). n-fib(m) elements are moved to B. fib(m+1)-n elements are moved to C. n-fib(m) elements from A and B are merged (pushed) to C. After the first merge, C ends up with n-fib(m) runs of size 2, and fib(m+1)-n runs of size 1 = fib(m-1) runs. B is emptied. A ends up with (n) - (fib(m+1)-n) - 2(n-fib(m)) = 2 fib(m) - fib(m+1) = fib(m) - fib(m-1) = fib(m-2) runs of size 1. In the case that n = fib(m), then fib(m-1) elements are moved to B, leaving fib(m-2) elements in A.
Wiki article also describes a similar situation to the 3 stack sort with tape drives written forward and read backwards, but doesn't mention the details of how to distribute dummy runs (runs of size 0) at the start, but this was probably included in that 55 year old publication mentioned by greybeard.
http://en.wikipedia.org/wiki/Polyphase_merge_sort
I wrote a C++ example, but since the question asked for Java (example code below), I'll provide a link to a zip for the C++ example. Instead of a stack class, the C++ example uses arrays with a stack pointer for each array (ppmrg3s.cpp). The zip also has a regular poly phase merge sort using arrays (ppmrg.cpp).
http://rcgldr.net/misc/ppmrg.zip
Example java code. On my system, Intel 2600K, 3.4ghz, Win 7 64 bit, it sorts 16 million doubles in about 4 seconds.
public class ppmrg3s {
static final int[] FIBTBL =
{ 0, 1, 1, 2, 3, 5,
8, 13, 21, 34, 55, 89,
144, 233, 377, 610, 987, 1597,
2584, 4181, 6765, 10946, 17711, 28657,
46368, 75025, 121393, 196418, 317811, 514229,
832040, 1346269, 2178309, 3524578, 5702887, 9227465,
14930352, 24157817, 39088169, 63245986, 102334155, 165580141,
267914296, 433494437, 701408733,1134903170,1836311903};
// return index of largest fib() <= n
static int flfib(int n)
{
int lo = 0;
int hi = 47;
while((hi - lo) > 1){
int i = (lo + hi)/2;
if(n < FIBTBL[i]){
hi = i;
continue;
}
if(n > FIBTBL[i]){
lo = i;
continue;
}
return i;
}
return lo;
}
// poly phase merge sort using 3 stacks
static void ppmrg3s(dstack a, dstack b, dstack c)
{
if(a.size() < 2)
return;
int ars = 1; // init run sizes
int brs = 1;
int asc = 0; // no size change
int bsc = 0;
int csc = 0;
int scv = 0-1; // size change value
boolean dsf; // == 1 if descending sequence
{ // block for local variable scope
int f = flfib(a.size()); // FIBTBL[f] >= size >= FIBTBL[f-1]
dsf = ((f%3) == 0); // init compare flag
if(FIBTBL[f] == a.size()){ // if exact fibonacci size,
for (int i = 0; i < FIBTBL[f - 1]; i++) { // move to b
b.push(a.pop());
}
} else { // else move to b, c
// update compare flag
dsf ^= 1 == ((a.size() - FIBTBL[f]) & 1);
// i = excess run count
int i = a.size() - FIBTBL[f];
// j = dummy run count
int j = FIBTBL[f + 1] - a.size();
// move excess elements to b
do{
b.push(a.pop());
}while(0 != --i);
// move dummy count elements to c
do{
c.push(a.pop());
}while(0 != --j);
csc = c.size();
}
} // end block scope
while(true){ // start merge pass
if(asc == a.size()){ // check for size count change
ars += scv; // (due to dummy run size == 0)
scv = 0-scv;
asc = 0;
csc = c.size();
}
if(bsc == b.size()){
brs += scv;
scv = 0-scv;
bsc = 0;
csc = c.size();
}
int arc = ars; // init run counters
int brc = brs;
while(true){ // start merge pair of runs
if(dsf ^ (a.peek() <= b.peek())){
c.push(a.pop()); // move a to c
if(--arc != 0) // if not end a
continue; // continue back to compare
do{ // else move rest of b run to c
c.push(b.pop());
}while(0 != --brc);
break; // and break
} else {
c.push(b.pop()); // move b to c
if(0 != --brc) // if not end b
continue; // continue back to compare
do{ // else move rest of a run to c
c.push(a.pop());
}while(0 != --arc);
break; // and break
}
} // end merge pair of runs
dsf ^= true; // toggle compare flag
if(b.empty()){ // if end b
if(a.empty()) // if end a, done
break;
b.swap(c); // swap b, c
brs += ars;
if (0 == asc)
bsc = csc;
} else { // else not end b
if(!a.empty()) // if not end a
continue; // continue back to merge pair
a.swap(c); // swap a, c
ars += brs;
if (0 == bsc)
asc = csc;
}
}
a.swap(c); // return sorted stack in a
}
I created a fast stack class that uses a fixed maximum size array of doubles that includes a swap function member:
class dstack{
double []ar; // array
int sz; // size
int sp; // stack pointer
public dstack(int sz){ // constructor with size
this.ar = new double[sz];
this.sz = sz;
this.sp = sz;
}
public void push(double d){
this.ar[--sp] = d;
}
public double pop(){
return this.ar[sp++];
}
public double peek(){
return this.ar[sp];
}
public boolean empty(){
return sp == sz;
}
public int size(){
return sz-sp;
}
public void swap(dstack othr){
double []tempar = othr.ar;
int tempsz = othr.sz;
int tempsp = othr.sp;
othr.ar = this.ar;
othr.sz = this.sz;
othr.sp = this.sp;
this.ar = tempar;
this.sz = tempsz;
this.sp = tempsp;
}
}
Test program. It uses random integers (nextInt), that get converted to doubles during a.push(...). This made the early debugging easier. For other platforms, or to follow with debug, use a smaller number for NUMELEM, which is the number of elements.
static final int NUMELEM = 16*1024*1024;
public static void main(String[] args) {
dstack a = new dstack(NUMELEM);
dstack b = new dstack(NUMELEM);
dstack c = new dstack(NUMELEM);
Random r = new Random();
for(int i = 0; i < NUMELEM; i++){
a.push(r.nextInt(NUMELEM));
}
long bgn, end;
bgn = System.currentTimeMillis();
ppmrg3s(a, b, c);
end = System.currentTimeMillis();
double d;
d = a.pop();
while(!a.empty()){
if(d > a.peek()){
System.out.println("error");
break;
}
d = a.pop();
}
System.out.println("milliseconds");
System.out.println(end-bgn);
}
A simple program to take values from an array and then print them to a command console would be.
import java.util.*;
public class StackSort
{
static Stack<Double> A = new Stack<Double>();
public void createStackA()
{
double[] x = {-10,5, 2, 1, 9, 0, 10};
for (int i = 0; i < x.length; i++)
{
A.push(x[i]);
}
}
public void sortStackA(Stack<Double> C)
{
Stack<Double> B = new Stack<Double>();
while(!C.isEmpty())
{
double s1 = (double) C.pop();
while(!B.isEmpty() && (B.peek() > s1))
{
C.push(B.pop());
}
B.push(s1);
}
System.out.println(B);
}
public static void main(String[] args)
{
StackSort sS = new StackSort();
sS.createStackA();
sS.sortStackA(A);
}
}
for a starting hint, check the shunting-yard algorithm it is a similar approach in that operators (i.e values) are pushed to a stack and popped to another stack (i.e output queue) depending on their relative priority (i.e value)
The algorithm has 3 stacks, a) input queue (lets say A), b) operator stack (lets say B) and c) output queue (lets say C), now try to translate this into an algorithm for sorting
This should do:
Move all items from stack A to stack B, store maximum value found in 'x'.
Move all items from stack B to stack A, except those with value 'x' determined from previous stem. Move those to C instead.
Repeat until both A and B are empty.
Objective: Finding the least amount of movement required to reach destination.
Scenario: in a 2D Array 8*8 with elements such as the following:
*......B
........
****.**.
.A....*.
........
....**..
........
....*...
where
" A " represents the starting point.
" B " represents the destination point.
" * " represents an obstacle.
" . " represents an empty cell.
Currently I have done the following code:
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
class main
{
public static void main(String args[]) throws FileNotFoundException,IOException
{
FileInputStream FS = new FileInputStream("path.in");
DataInputStream DS = new DataInputStream(FS);
BufferedReader buffer = new BufferedReader(new InputStreamReader(DS));
String strLine = buffer.readLine();
int testCase = Integer.parseInt(strLine);
int R,C;
for(int i = 0;i < testCase;i++)
{
strLine = buffer.readLine();
String input[] = strLine.split(" ");
R = Integer.parseInt(input[0]);
C = Integer.parseInt(input[1]);
char[][] array = new char[R][C];
int sCoordX = 0;
int sCoordY = 0;
int eCoordX = 0;
int eCoordY = 0;
for(int j = 0; j < R ; j++)
{
strLine = buffer.readLine();
for(int k = 0;k < C;k++)
{
array[j][k] = strLine.charAt(k);
if(array[j][k] == 'A')
{
sCoordX = j;
sCoordY = k;
}
if(array[j][k] == 'B')
{
eCoordX = j;
eCoordY = k;
}
}
}
boolean reached = false;
int counter = 0;
int posX = sCoordX;
int posY = sCoordY;
while(!reached)
{
if(array[posX][posY] == 'B')
{
reached = true;
System.out.println("You are in goal!");
System.out.println(array[posX][posY]);
System.out.println("Number of steps:"+counter);
}
if(!reached && posX > eCoordX)
{
posX--;
counter++;
}
else if(!reached && posX < eCoordX)
{
posX++;
counter++;
}
if(!reached && posY > eCoordY)
{
posY--;
counter++;
}
else if(!reached && posY < eCoordY)
{
posY++;
counter++;
}
}
}
}
}
It does the job of finding the "shortest" amount of steps required to reach the destination however it will consider anything/obstacles as empty cells that it can move to.
I'm currently unable to figure out a way to code it in a way that will allow it to recognize a proper decision for the next movement.
I'm thinking of using array lists and some algorithm,however I tried reading some algorithms such as the Dijkstra's algorithm but it seemed really confusing,can anybody help me understand it in a very easy manner to implement it in java?
//-(sorry for my coding skills,I'm still a beginner)-
You don't need any special algorithm for this task, only a breadth-first search in a graph. Consider points that are reachable in 1 step as the first level of your graph, points thats are reachable in 2 steps(those ones are connected to any of the first level points, but not to the source point) as the second level, etc.
First visit the points which are directly reachable from the source point, then visit the second-level points, then visit the third-level points. You can achieve this by storing the nodes in a list. First you visit the source, and push the neighbouring nodes to the end of your list. Then you visit each node in your list, and push their neighbouring nodes to the end of the list, if they are not in the list so far. Once you reach the target node, you are done. You can store the level of each node, and also, you can store the preceding node, so you can find the path backwards from the target node.
One important thing to note: don't add obstacles to your list, this way there will be no routes crossing that point.
I'm trying to write a program that'll find the MST of a given undirected weighted graph with Kruskal's and Prim's algorithms. I've successfully implemented Kruskal's algorithm in the program, but I'm having trouble with Prim's. To be more precise, I can't figure out how to actually build the Prim function so that it'll iterate through all the vertices in the graph. I'm getting some IndexOutOfBoundsException errors during program execution. I'm not sure how much information is needed for others to get the idea of what I have done so far, but hopefully there won't be too much useless information.
This is what I have so far:
I have a Graph, Edge and a Vertex class.
Vertex class mostly just an information storage that contains the name (number) of the vertex.
Edge class can create a new Edge that has gets parameters (Vertex start, Vertex end, int edgeWeight). The class has methods to return the usual info like start vertex, end vertex and the weight.
Graph class reads data from a text file and adds new Edges to an ArrayList. The text file also tells us how many vertecis the graph has, and that gets stored too.
In the Graph class, I have a Prim() -method that's supposed to calculate the MST:
public ArrayList<Edge> Prim(Graph G) {
ArrayList<Edge> edges = G.graph; // Copies the ArrayList with all edges in it.
ArrayList<Edge> MST = new ArrayList<Edge>();
Random rnd = new Random();
Vertex startingVertex = edges.get(rnd.nextInt(G.returnVertexCount())).returnStartingVertex(); // This is just to randomize the starting vertex.
// This is supposed to be the main loop to find the MST, but this is probably horribly wrong..
while (MST.size() < returnVertexCount()) {
Edge e = findClosestNeighbour(startingVertex);
MST.add(e);
visited.add(e.returnStartingVertex());
visited.add(e.returnEndingVertex());
edges.remove(e);
}
return MST;
}
The method findClosesNeighbour() looks like this:
public Edge findClosestNeighbour(Vertex v) {
ArrayList<Edge> neighbours = new ArrayList<Edge>();
ArrayList<Edge> edges = graph;
for (int i = 0; i < edges.size() -1; ++i) {
if (edges.get(i).endPoint() == s.returnVertexID() && !visited(edges.get(i).returnEndingVertex())) {
neighbours.add(edges.get(i));
}
}
return neighbours.get(0); // This is the minimum weight edge in the list.
}
ArrayList<Vertex> visited and ArrayList<Edges> graph get constructed when creating a new graph.
Visited() -method is simply a boolean check to see if ArrayList visited contains the Vertex we're thinking about moving to. I tested the findClosestNeighbour() independantly and it seemed to be working but if someone finds something wrong with it then that feedback is welcome also.
Mainly though as I mentioned my problem is with actually building the main loop in the Prim() -method, and if there's any additional info needed I'm happy to provide it.
Thank you.
Edit: To clarify what my train of thought with the Prim() method is. What I want to do is first randomize the starting point in the graph. After that, I will find the closest neighbor to that starting point. Then we'll add the edge connecting those two points to the MST, and also add the vertices to the visited list for checking later, so that we won't form any loops in the graph.
Here's the error that gets thrown:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at Graph.findClosestNeighbour(graph.java:203)
at Graph.Prim(graph.java:179)
at MST.main(MST.java:49)
Line 203: return neighbour.get(0); in findClosestNeighbour()
Line 179: Edge e = findClosestNeighbour(startingVertex); in Prim()
Vertex startingVertex = edges.get(rnd.nextInt(G.returnVertexCount())).returnStartingVertex();
This uses the vertex count to index an edge list, mixing up vertices and edges.
// This is supposed to be the main loop to find the MST, but this is probably horribly wrong..
while (MST.size() < returnVertexCount()) {
Edge e = findClosestNeighbour(startingVertex);
MST.add(e);
visited.add(e.returnStartingVertex());
visited.add(e.returnEndingVertex());
edges.remove(e);
}
This shouldn't be passing the same startingVertex to findClosestNeighbour each time.
public Edge findClosestNeighbour(Vertex v) {
ArrayList<Edge> neighbours = new ArrayList<Edge>();
ArrayList<Edge> edges = graph;
for (int i = 0; i < edges.size() -1; ++i) {
if (edges.get(i).endPoint() == s.returnVertexID() && !visited(edges.get(i).returnEndingVertex())) {
neighbours.add(edges.get(i));
}
}
return neighbours.get(0); // This is the minimum weight edge in the list.
}
What is s here? This doesn't look like it's taking the edge weights into account. It's skipping the last edge, and it's only checking the ending vertex, when the edges are non-directional.
// Simple weighted graph representation
// Uses an Adjacency Linked Lists, suitable for sparse graphs /*undirected
9
A
B
C
D
E
F
G
H
I
A B 1
B C 2
C E 7
E G 1
G H 8
F H 3
F D 4
D E 5
I F 9
I A 3
A D 1
This is the graph i used saved as graph.txt
*/
import java.io.*;
import java.util.Scanner;
class Heap
{
private int[] h; // heap array
private int[] hPos; // hPos[h[k]] == k
private int[] dist; // dist[v] = priority of v
private int MAX;
private int N; // heap size
// The heap constructor gets passed from the Graph:
// 1. maximum heap size
// 2. reference to the dist[] array
// 3. reference to the hPos[] array
public Heap(int maxSize, int[] _dist, int[] _hPos)
{
N = 0;
MAX = maxSize;
h = new int[maxSize + 1];
dist = _dist;
hPos = _hPos;
}
public boolean isEmpty()
{
return N == 0;
}
public void siftUp( int k)
{
int v = h[k];
h[0] = 0;
dist[0] = Integer.MIN_VALUE;
//vertex using dist moved up heap
while(dist[v] < dist[h[k/2]]){
h[k] = h[k/2]; //parent vertex is assigned pos of child vertex
hPos[h[k]] = k;//hpos modified for siftup
k = k/2;// index of child assigned last parent to continue siftup
}
h[k] = v;//resting pos of vertex assigned to heap
hPos[v] = k;//index of resting pos of vertex updated in hpos
//display hpos array
/* System.out.println("\nThe following is the hpos array after siftup: \n");
for(int i = 0; i < MAX; i ++){
System.out.println("%d", hPos[i]);
}
System.out.println("\n Following is heap array after siftup: \n");
for (int i = 0; i < MAX; i ++ ){
System.out.println("%d" , h[i]);
}*/
}
//removing the vertex at top of heap
//passed the index of the smallest value in heap
//siftdown resizes and resorts heap
public void siftDown( int k)
{
int v, j;
v = h[k];
while(k <= N/2){
j = 2 * k;
if(j < N && dist[h[j]] > dist[h[j + 1]]) ++j; //if node is > left increment j child
if(dist[v] <= dist[h[j]]) break;//if sizeof parent vertex is less than child stop.
h[k] = h[j];//if parent is greater than child then child assigned parent pos
hPos[h[k]] = k;//update new pos of last child
k = j;//assign vertex new pos
}
h[k] = v;//assign rest place of vertex to heap
hPos[v] = k;//update pos of the vertex in hpos array
}
public void insert( int x)
{
h[++N] = x;//assign new vertex to end of heap
siftUp( N);//pass index at end of heap to siftup
}
public int remove()
{
int v = h[1];
hPos[v] = 0; // v is no longer in heap
h[N+1] = 0; // put null node into empty spot
h[1] = h[N--];//last node of heap moved to top
siftDown(1);//pass index at top to siftdown
return v;//return vertex at top of heap
}
}
class Graph {
class Node {
public int vert;
public int wgt;
public Node next;
}
// V = number of vertices
// E = number of edges
// adj[] is the adjacency lists array
private int V, E;
private Node[] adj;
private Node z;
private int[] mst;
// used for traversing graph
private int[] visited;
private int id;
// default constructor
public Graph(String graphFile) throws IOException
{
int u, v;
int e, wgt;
Node t;
FileReader fr = new FileReader(graphFile);
BufferedReader reader = new BufferedReader(fr);
String splits = " +"; // multiple whitespace as delimiter
String line = reader.readLine();
String[] parts = line.split(splits);
System.out.println("Parts[] = " + parts[0] + " " + parts[1]);
V = Integer.parseInt(parts[0]);
E = Integer.parseInt(parts[1]);
// create sentinel node
z = new Node();
z.next = z;
// create adjacency lists, initialised to sentinel node z
adj = new Node[V+1];
for(v = 1; v <= V; ++v)
adj[v] = z;
// read the edges
System.out.println("Reading edges from text file");
for(e = 1; e <= E; ++e)
{
line = reader.readLine();
parts = line.split(splits);
u = Integer.parseInt(parts[0]);
v = Integer.parseInt(parts[1]);
wgt = Integer.parseInt(parts[2]);
System.out.println("Edge " + toChar(u) + "--(" + wgt + ")--" + toChar(v));
// write code to put edge into adjacency matrix
t = new Node(); t.vert = v; t.wgt = wgt; t.next = adj[u]; adj[u] = t;
t = new Node(); t.vert = u; t.wgt = wgt; t.next = adj[v]; adj[v] = t;
}
}
// convert vertex into char for pretty printing
private char toChar(int u)
{
return (char)(u + 64);
}
// method to display the graph representation
public void display() {
int v;
Node n;
for(v=1; v<=V; ++v){
System.out.print("\nadj[" + toChar(v) + "] ->" );
for(n = adj[v]; n != z; n = n.next)
System.out.print(" |" + toChar(n.vert) + " | " + n.wgt + "| ->");
}
System.out.println("");
}
//use the breath first approach to add verts from the adj list to heap
//uses 3 arrays where array = # of verts in graph
//parent array to keep track of parent verts
// a dist matrix to keep track of dist between it and parent
//hpos array to track pos of vert in the heap
public void MST_Prim(int s)
{
int v, u;
int wgt, wgt_sum = 0;
int[] dist, parent, hPos;
Node t;
//declare 3 arrays
dist = new int[V + 1];
parent = new int[V + 1];
hPos = new int[V +1];
//initialise arrays
for(v = 0; v <= V; ++v){
dist[v] = Integer.MAX_VALUE;
parent[v] = 0;
hPos[v] = 0;
}
dist[s] = 0;
//d.dequeue is pq.remove
Heap pq = new Heap(V, dist, hPos);
pq.insert(s);
while (! pq.isEmpty())
{
// most of alg here
v = pq.remove();
wgt_sum += dist[v];//add the dist/wgt of vert removed to mean spanning tree
//System.out.println("\nAdding to MST edge {0} -- ({1}) -- {2}", toChar(parent[v]), dist[v], toChar[v]);
dist[v] = -dist[v];//mark it as done by making it negative
for(t = adj[v]; t != z; t = t.next){
u = t.vert;
wgt = t.wgt;
if(wgt < dist[u]){ //weight less than current value
dist[u] = wgt;
parent[u] = v;
if(hPos[u] == 0)// not in heap insert
pq.insert(u);
else
pq.siftUp(hPos[u]);//if already in heap siftup the modified heap node
}
}
}
System.out.print("\n\nWeight of MST = " + wgt_sum + "\n");
//display hPos array
/*System.out.println("\nhPos array after siftUp: \n");
for(int i = 0; i < V; i ++){
System.out.println("%d", hPos[i]);
}*/
mst = parent;
}
public void showMST()
{
System.out.print("\n\nMinimum Spanning tree parent array is:\n");
for(int v = 1; v <= V; ++v)
System.out.println(toChar(v) + " -> " + toChar(mst[v]));
System.out.println("");
}
}
public class PrimLists {
public static void main(String[] args) throws IOException
{
int s = 2;
String fname = "graph.txt";
Graph g = new Graph(fname);
g.display();
}
}