Ok.. so I decided to try linked lists in Java rather than the usual C++ which I'm used to references an pointers in..
Traversal can be Up, Down, Left, Right for a center node. For nodes in the corners, they only move two directions and nodes on the edges can move 3 directions.. All others can move 4.
Problem:
When my program leaves the constructor, my nodes are deleted somehow :S When I use the get/set, it cannot traverse the links because they are null.. Except for the first node.
My node is:
package linkedlist;
public class Node {
public Node Up, Down, Left, Right;
public int Value;
public Node() {
Value = -1;
Up = Down = Left = Right = null;
}
}
I do implementation like:
package linkedlist;
public class Matrix {
private int Width, Height;
private Node Reference;
public Matrix(int Width, int Height) {
Reference = new Node();
this.Width = Width; this.Height = Height;
Node RowIterator = Reference, ColumnIterator = Reference;
for (int I = 0; I < Height; ++I) {
for (int J = 0; J < Width; ++J) {
if (I == 0) {
if (J < Width - 1) {
RowIterator.Right = new Node();
RowIterator.Right.Left = RowIterator;
RowIterator = RowIterator.Right;
}
}
else {
if (I < Height - 1) {
ColumnIterator.Down = new Node();
}
RowIterator = ColumnIterator;
RowIterator.Right = new Node();
RowIterator.Up = ColumnIterator;
RowIterator.Up.Down = RowIterator;
RowIterator.Right.Left = RowIterator;
RowIterator.Right.Up = RowIterator.Up.Right;
RowIterator = RowIterator.Right;
ColumnIterator = ColumnIterator.Down;
}
}
}
}
public void SetValue(int I, int J, int Value) {
//Same as get except it sets rather than returns..
}
public int GetValue(int I, int J) {
RowIterator = ColumnIterator = Reference;
for (int K = 0; K < J; ++K) {
for (int L = 0; L < I; ++L) {
RowIterator = RowIterator.Right;
}
ColumnIterator = ColumnIterator.Down;
RowIterator = ColumnIterator;
}
return RowIterator.Value;
}
}
And the main like:
package linkedlist;
public class LinkedList {
public static void main(String[] args) {
Matrix M = new Matrix(6, 6);
M.SetValue(3, 3, 10);
}
}
So when I attempt to set the value at near middle of the matrix, it throws a null pointer error.. If I attempt to set it in the constructor, it works just fine.. Thus my nodes must be somehow getting garbage cleaned..
You iterate across the row as many times as you iterate down the column. I.e., in your example, the actual node that is accessed is (9, 3), out of the bounds of your Matrix.
Instead, you should iterate once across the row, and then once down the column.
for (int K = 0; K < J; ++K) {
Iterator = Iterator.Down;
}
for (int L = 0; L < I; ++L) {
Iterator = Iterator.Right;
}
Any particular reason you aren't just using a 2-dimensional array?
Related
example - there is an unconnected graph with vertices A - B - C - D and E - F - G. (a hyphen means that they are connected). The code below is using depth-first traversal, I need to modify it to display all connected vertices. eg:
list0: ABCD
list1: EFG
etc...
I don't understand how to implement this.
public class Graph {
private final int MAX_VERTS = 20;
private Vertex vertexList[];
private int matrix[][];
private int countV;
private StackX theStack;
// ------------------------------------------------------------
public Graph() {
vertexList = new Vertex[MAX_VERTS];
matrix = new int[MAX_VERTS][MAX_VERTS];
countV = 0;
for (int x = 0; x < MAX_VERTS; x++)
for (int y = 0; y < MAX_VERTS; y++)
matrix[x][y] = 0;
theStack = new StackX();
}
// -------------------------------------------------------------
public void addVertex(char label) {
vertexList[countV++] = new Vertex(label);
}
// -------------------------------------------------------------
public void addEdge(int x, int y) {
matrix[x][y] = 1;
matrix[y][x] = 1;
}
// -------------------------------------------------------------
public void displayVertex(int v) {
System.out.print(vertexList[v].label);
}
public void dfs() {
vertexList[0].wasVisited = true;
displayVertex(0);
theStack.push(0);
while (!theStack.isEmpty()) {
int v = getUnvisitedVertex(theStack.peek());
if (v == -1)
theStack.pop();
else
{
vertexList[v].wasVisited = true;
displayVertex(v);
theStack.push(v);
}
}
for (int j = 0; j < countV; j++)
vertexList[j].wasVisited = false;
}
// ------------------------------------------------------------
public int getUnvisitedVertex(int vertex) {
for (int j = 0; j < countV; j++)
if (matrix[vertex][j] == 1 && !vertexList[j].wasVisited) {
return j;
}
return -1;
}
}
Your DFS does not need to modified. It needs to be put inside a loop so that each pass will discover one of the lists of connected nodes that your are looking for
LOOP
Select arbitrary vertex
DFS, saving each visited vertex in list.
LOOP over visited vertices
remove from graph
LOOP END
IF all vertices removed
BREAK out of loop
Start new list
LOOP END
Output lists
I attempted to follow this pseudocode on wikipedia https://en.wikipedia.org/wiki/Maze_generation_algorithmRandomized_Prim's_algorithm
but my code just generates a full grid. I seem to be missing something in my understanding of what the algorithm does. Can someone help explain what I'm doing wrong?
I've looked at a few sources but I can't wrap my head around it
public class MazeGen {
private int dimension, nodeCounter;
private Node[][] nodes;
private List<Edge> walls;
public static void main(String[] args) {
MazeGen g = new MazeGen(20);
g.generate();
g.printMaze();
}
private void generate() {
pickCell();
generateMaze();
}
private void generateMaze() {
while (!walls.isEmpty()) {
int v;
Edge wall = walls.get(ThreadLocalRandom.current().nextInt(walls.size()));
if ((!wall.nodes[0].visited && wall.nodes[1].visited)
|| (wall.nodes[0].visited && !wall.nodes[1].visited)) {
if (!wall.nodes[0].visited)
v = 0;
else
v = 1;
includeNode(wall.nodes[v]);
wall.nodes[Math.abs(v - 1)].visited = true;
}
walls.remove(wall);
}
}
private void pickCell() {
int i = ThreadLocalRandom.current().nextInt(dimension);
int j = ThreadLocalRandom.current().nextInt(dimension);
includeNode(nodes[i][j]);
}
private void includeNode(Node node) {
node.visited = true;
node.partOfMaze = true;
walls.addAll(node.edges);
}
public void printMaze() {
for (int i = 0; i < dimension; i++) {
System.out.println();
for (int j = 0; j < dimension; j++) {
if (nodes[i][j].partOfMaze) {
System.out.print(".");
} else
System.out.print("p");
}
}
}
public MazeGen(int n) {
nodes = new Node[n][n];
walls = new ArrayList<Edge>();
dimension = n;
createNodes();
connectAdjacents();
}
private void connectAdjacents() {
for (int i = 0; i < dimension; i++) {
for (int j = 0; j < dimension; j++) {
verifyConnection(i, j, i, j + 1);
verifyConnection(i, j, i + 1, j);
}
}
}
private void verifyConnection(int i, int j, int arg1, int arg2) {
if (arg1 < dimension && arg2 < dimension)
connect(i, j, arg1, arg2);
}
private void createNodes() {
for (int i = 0; i < dimension; i++) {
for (int j = 0; j < dimension; j++) {
nodes[i][j] = new Node();
}
}
}
private void connect(int row, int col, int row2, int col2) {
nodes[row][col].edges.add(new Edge(nodes[row][col], nodes[row2][col2]));
nodes[row2][col2].edges.add(new Edge(nodes[row][col], nodes[row2][col2]));
}
private class Node {
boolean visited, partOfMaze;
int number;
List<Edge> edges;
Node() {
number = nodeCounter++;
edges = new ArrayList<Edge>();
}
#Override
public String toString() {
return String.valueOf(number);
}
}
private class Edge {
Node[] nodes;
Edge(Node n, Node n2) {
nodes = new Node[2];
nodes[0] = n;
nodes[1] = n2;
}
#Override
public String toString() {
return nodes[0] + "-" + nodes[1];
}
}
I think that your algorithm is correct but you don't keep the correct output.
All the nodes should be part of the maze. The walls that should be part of the maze are the walls that connect two visited nodes when you proccess them.
make another array of output walls, and set the values in the generateMaze method.
private void generateMaze() {
while (!walls.isEmpty()) {
int v;
Edge wall = walls.get(ThreadLocalRandom.current().nextInt(walls.size()));
if ((!wall.nodes[0].visited && wall.nodes[1].visited)
|| (wall.nodes[0].visited && !wall.nodes[1].visited)) {
if (!wall.nodes[0].visited)
v = 0;
else
v = 1;
includeNode(wall.nodes[v]);
wall.nodes[Math.abs(v - 1)].visited = true;
/////////////////////////////////////
// remove this wall from the output walls
/////////////////////////////////////
} else {
////////////////////////////////
// add this wall to the output walls
////////////////////////////////
}
walls.remove(wall);
}
}
Forget Wikipedia, they censor free speech and manipulate information, especially in political and social areas. For that reason I also deleted all my additions to the Wikipedia page on "maze generation" (see page history).
The idea of "Prim's" MST algorithm is to maintain a "cut" (a set of edges) between disconnected subgraphs and always select the cheapest edge to connect these subgraphs. Visited vertices are marked to avoid generating cycles.
This can be used for maze generation by using edge random weights in a full grid graph or by starting with an empty grid graph and adding randomly weighted edges on the fly.
See my GitHub repository on maze generation for details:
https://github.com/armin-reichert/mazes
https://github.com/armin-reichert/mazes/blob/master/mazes-algorithms/src/main/java/de/amr/maze/alg/mst/PrimMST.java
public void createMaze(int x, int y) {
cut = new PriorityQueue<>();
expand(grid.cell(x, y));
while (!cut.isEmpty()) {
WeightedEdge<Integer> minEdge = cut.poll();
int u = minEdge.either(), v = minEdge.other();
if (isCellUnvisited(u) || isCellUnvisited(v)) {
grid.addEdge(u, v);
expand(isCellUnvisited(u) ? u : v);
}
}
}
private void expand(int cell) {
grid.set(cell, COMPLETED);
grid.neighbors(cell).filter(this::isCellUnvisited).forEach(neighbor -> {
cut.add(new WeightedEdge<>(cell, neighbor, rnd.nextInt()));
});
}
So I have some code which finds items in an array which are greater than itself in respect to its position. So for example if the list was:
[1,3,2]
2 and 3 would need to be swapped, to be ordered so they would be added to the adjacency list.
However, for slightly larger problems I want to be able to find the vertex cover of the graph such that of a graph is a set of vertices such that each edge of the graph is incident to at least one vertex of the set
Want I'm looking for is something like this for example [4,2,3,1]:
public class VertexCover{
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int[] row = {4, 2, 1, 5};
Vertex[] adjLists = new Vertex[row.length];
for (int i = 0; i < adjLists.length; i++) {
adjLists[i] = new Vertex(row[i], null);
}
int max = -1;
for (int i = 0; i < row.length; i++) {
for (int j = 0; j < row.length; j++) {
if (adjLists[i].value > adjLists[j].value && i < j) {
adjLists[i].adjList = new Neighbour(j, adjLists[i].adjList);
adjLists[j].adjList = new Neighbour(i, adjLists[j].adjList);
}
}
}
for (int i = 0; i < adjLists.length; i++) {
System.out.print(adjLists[i].value);
for (Neighbour neighbour = adjLists[i].adjList; neighbour != null; neighbour = neighbour.next) {
System.out.print("---->" + adjLists[neighbour.vertexNum].value);
}
System.out.println("");
}
}
}
class Vertex {
int value;
Neighbour adjList;
Vertex(int value, Neighbour neighbours) {
this.value = value;
this.adjList = neighbours;
}
}
class Neighbour {
int vertexNum;
public Neighbour next;
public Neighbour(int vnum, Neighbour next) {
this.vertexNum = vnum;
this.next = next;
}
}
I can't find anything on this, apart from its np complete.
I have the following code, Dijkstra's algorithm, that I made using Wikipedia's article on the algorithm.
For the given graph (see image) and starting node (1), it returns 5 as distance to node (4), which is obviously false. However, when going from node (4), it returns 4 as distance to (1), which is correct. What is wrong in my code?
//source = starting point, adj[] = adjacency list
private static int dijkstra (int source, ArrayList<Road>[] adj) {
HashSet<Integer> vertices = new HashSet<>();
int[] dist = new int[adj.length];
int[] prev = new int[adj.length];
for (int i = 0; i < adj.length; i++) {
dist[i] = Integer.MAX_VALUE;
prev[i] = Integer.MAX_VALUE;
vertices.add(i);
}
dist[source] = 0;
while (!vertices.isEmpty()) {
int current = Integer.MAX_VALUE;
for (int v: vertices) {
if (dist[v] < current) {
current = v;
}
}
vertices.remove(current);
for (Road v: adj[current]) {
int alt = dist[current] + v.distance;
if (alt < dist[v.end]) {
dist[v.end] = alt;
prev[v.end] = current;
}
}
}
}
class Road {
int end;
int distance;
}
//This loop builds adjacency list from input such as "1 3 2", where 1 represents
// starting node, 3 represents end node and 2 represents weight of that edge.
//start and end values are decremented in order to be 0-indexed
for (int i = 0; i < M; i++) {
int start = in.nextInt() - 1;
int end = in.nextInt() - 1 ;
int dist = in.nextInt();
adj[start].add(new Road(end, dist));
adj[end].add(new Road(start, dist));
}
This piece of code is causing the error:
int current = Integer.MAX_VALUE;
for (int v: vertices) {
if (dist[v] < current) {
current = v;
}
}
I assume it's supposed to search the unvisited node that has the shortest path from the start-vertex. But this should look rather like this:
int currentPathLen = Integer.MAX_VALUE, current = -1;
for (int v: vertices) {
if (dist[v] < currentPathLen) {
current = v;
currentPathLen = dist[current];
}
}
I'm writing a program to find the longest path for a DAG with input from standard in.I finally got it to compile, with it saying it is using unchecked or unsafe operations due to my Array list, but I am getting an index out of bounds error and it feels like I have tried changing every loop I must be missing something, thanks in advanced for any tips.
Here is my code:
import java.io.*;
import java.util.*;
public class countLongPaths
{
static final int NINF = Integer.MIN_VALUE;
public class AdjListNode
{
private int v;
private int weight;
AdjListNode(int inV, int inW)
{
v = inV;
weight = inW;
}
int getV()
{
return v;
}
int getWeight()
{
return weight;
}
}//end of adj list class
public class Graph
{
private int V;
private LinkedList<AdjListNode>adj[];
//set up graph with given number of verticies
Graph(int v)
{
V=v;
adj = new LinkedList[V];
for (int i = 0; i < v; ++i)
adj[i] = new LinkedList<AdjListNode>();
}
//function to add edges to graph
void addEdge(int u, int v, int weight)
{
AdjListNode node = new AdjListNode(v,weight);
adj[u].add(node);// Add v to u's list
}
//function to set order to go through vertices
void setOrder(int v, Boolean visited[], Stack stack)
{
//Set node to visited when on it
visited[v] = true;
Integer i;
//for all nodes connected to current repeat
Iterator<AdjListNode> it = adj[v].iterator();
while (it.hasNext())
{
AdjListNode node =it.next();
if (!visited[node.getV()])
setOrder(node.getV(), visited, stack);
}
//Once done with current add it to the stack
stack.push(new Integer(v));
}
//function to find longest paths from s
int longestPath()
{
Stack stack = new Stack();
int LP[] = new int[V];
//set all vertices to unvisited
Boolean visited[] = new Boolean[V];
for(int i = 1; i <= V; i++)
visited[i] = false;
//call set order function from each vertex
for (int i = 1; i <= V; i++)
{
if(visited[i] == false)
setOrder(i, visited, stack);
}
//initialize distaces to all verices as negative infinity
//set distace to source to 0
LP[1] = 0;
for(int i = 2; i <= V; i++)
LP[i] = NINF;
//go through vertices in order
while(stack.empty() == false)
{
int u = (int)stack.pop();
//update LP for adj vertices
Iterator<AdjListNode> it;
if (LP[u] != NINF)
{
it = adj[u].iterator();
while (it.hasNext())
{
AdjListNode i = it.next();
if(LP[i.getV()] < LP[u] + i.getWeight())
LP[i.getV()] = LP[u] + i.getWeight();
}
}
}
return LP[V];
}
}//end of graph class
//Method to make a new graph
public Graph newGraph(int number)
{
return new Graph(number);
}
public static void main(String[]args)
{
countLongPaths n = new countLongPaths();
int GN = 0;
int count = 1;
Scanner scan = new Scanner(System.in);
GN = scan.nextInt();
while (count<= GN)
{
int N = 0;// nodes
int M = 0;//edges
N = scan.nextInt();
M = scan.nextInt();
//setup a new graph
Graph g = n.newGraph(N);
//set edges for new graph
for(int i = 1; i <= M; i ++)
{
int I = scan.nextInt();
int J = scan.nextInt();
int W = scan.nextInt();
g.addEdge(I, J, W);
}
int dist = 0;
dist = g.longestPath();
System.out.println("graph number: " + count);
System.out.println("longest path: " + dist);
System.out.println("number of longest paths: ");
System.out.println();
count++;
}//end of while
}//end main
}//end program
EDIT 1
with current code this is the error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at countLongPaths$Graph.<init>(countLongPaths.java:36)
at countLongPaths.newGraph(countLongPaths.java:108)
at countLongPaths.main(countLongPaths.java:127)
As your stack trace says, the exception occurs in your Graph class constructor.
More specifically it happens inside the only line in your loop:
adj = new LinkedList[V];
for (int i = 0; i <= v; ++i)
adj[i] = new LinkedList<AdjListNode>();
Assuming you've meant both lowercase v and uppercase V to be the same variable, you're defining an array of size V which is indexed from 0 to V-1, but you're running on it from 0 to V (your condition is i <= V), which is why you're getting an IndexOutOfBoundsException.
Simply change the loop's condition (remove the =):
for (int i = 0; i < v; ++i)