Anyone know where I can obtain generic sample code for using an adjacency list to represent an undirected graph?
The graph data would be from a .txt file: The nodes are specified on the first line, separated by spaces. The edges are specified on the following lines, each edge on a separate line.
Like this...
1 2 3 4 5 6 7 8 9
1 2
1 4
1 3
2 4
2 5
3 6
4 6
5 7
5 8
6 9
7 9
8 9
My .txt file isn't connecting with the graph methods. I'm also getting the following NPE error:
Error: java.lang.NullPointerException
Creating an adjacency list & performing standard Graph ADT methods for the undirected graph.
//TON of imports up here (removed for now)
class Graph<V> implements GraphADT1 <V>{
// Map of adjacency lists for each node
private HashMap<Integer, LinkedList<Integer>> adj;
private ArrayList<V> vertices;
private HashMap<V, LinkedHashSet<V>> neighbors;
private HashMap<V, Set<V>> neighborsView;
private int edgeCount;
public Graph(int[] nodes) {
vertices = new ArrayList<V>();
neighbors = new HashMap<V, LinkedHashSet<V>>();
neighborsView = new HashMap<V, Set<V>>();
adj = new HashMap<Integer, LinkedList<Integer>>();
for (int i = 0; i < nodes.length; ++i) {
adj.put(i, new LinkedList<Integer>());
}
}
//Add Vertex Method
public void addVertex(V vid) {
vertices.add(vid);
LinkedHashSet<V> neighborV = new LinkedHashSet<V>();
neighbors.put(vid, neighborV);
neighborsView.put(vid, Collections.unmodifiableSet(neighborV));
}
// Removes Vertex Method
public void removeVertex(V vid) {
if(vertices.remove(vid)) {
LinkedHashSet<V> neighborV = neighbors.remove(vid);
for(V uid : neighborV) {
LinkedHashSet<V> neighborU = neighbors.get(uid);
neighborU.remove(vid);
--edgeCount;
}
neighborsView.remove(vid);
} else {
throw new NoSuchElementException("no such vertex");
}
}
//Add Edge Method
public void addEdge(V uid, V vid) {
LinkedHashSet<V> neighborU = neighbors.get(uid);
LinkedHashSet<V> neighborV = neighbors.get(vid);
if(neighborU == null) throw new NoSuchElementException("first argument not in graph");
if(neighborV == null) throw new NoSuchElementException("second argument not in graph");
if(neighborU.add(vid) && neighborV.add(uid)) {
++edgeCount;
}
}
//Remove Edge Method
public void removeEdge(V uid, V vid) {
LinkedHashSet<V> neighborU = neighbors.get(uid);
LinkedHashSet<V> neighborV = neighbors.get(vid);
if(neighborU == null) throw new NoSuchElementException("first argument not in graph");
if(neighborV == null) throw new NoSuchElementException("second argument not in graph");
if(neighborU.remove(vid) && neighborV.remove(uid)) {
--edgeCount;
} else {
throw new NoSuchElementException("no edge between vertices");
}
}
public void addNeighbor(int neighborV, int neighborU) {
adj.get(neighborV).add(neighborU);
}
public List<Integer> getNeighbors(int v) {
return adj.get(v);
}
public static void main(String[] args) {
try {
File file = new File("data.txt");
InputStreamReader streamReader = new InputStreamReader(
new FileInputStream(file));
BufferedReader br = new BufferedReader(streamReader);
String line = br.readLine();
if (line != null) {
// read nodes
String[] nodeNames = line.split(" ");
int[] nodes = new int[nodeNames.length];
for (int i = 0; i < nodes.length; ++i) {
nodes[i] = Integer.parseInt(nodeNames[i]);
}
// create graph
Graph V = new Graph(nodes);
// read edges
while ((line = br.readLine()) != null) {
String[] tokens = line.split(" ");
int neighborV = Integer.parseInt(tokens[0]);
int neighborU = Integer.parseInt(tokens[1]);
// we add neighbor to each node in both directions.
V.addNeighbor(neighborV, neighborU);
V.addNeighbor(neighborU, neighborV);
}
}
br.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception e) {
System.out.println("Error: " + e);
}
}
public Iterator<?> iteratorBFS(Object startVertex) {
return null;
}
public Iterator<?> iteratorDFS(Object startVertex) {
return null;
}
public boolean isEmpty() {
return size() == 0;
}
public boolean isConnected() {
return false;
}
public int size() {
return 0;
}
}
You can enclose your graph in class:
class Graph {
//Map of adjacency lists for each node
Map<Integer, List<Integer>> adj;
public Graph(int[] nodes) {
//your node labels are consecutive integers starting with one.
//to make the indexing easier we will allocate an array of adjacency one element larger than necessary
adj = new HashMap<Integer, LinkedList<Integer>>();
for (int i = 0; i < nodes.length; ++i) {
adj.put(i, new LinkedList<Integer>());
}
}
public addNeighbor(int v1, int v2) {
adj.get(v1).add(v2);
}
public List<Integer> getNeighbors(int v) {
return adj.get(v);
}
}
And then read it more or less like this:
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new StreamReader(System.in));
String line = br.readLine();
if (line != null) {
//read nodes
String[] nodeNames = line.split(" ");
int[] nodes = new int[nodeNames.length]
for (int i = 0; i < nodes.length; ++i) {
nodes[i] = Integer.parseInt(nodeNames[i]);
}
//create graph
Graph g = new Graph(nodes);
//read edges
while((line = br.readLine()) != null) {
String[] tokens = line.split(" ");
int v1 = Integer.parseInt(tokens[0]);
int v2 = Integer.parseInt(tokens[1]);
//we add neighbor to each node in both directions.
g.addNeighbor(v1, v2);
g.addNeighbor(v2, v1);
}
}
br.close();
}
catch(exceptions) {
handle them
}
}
public static void main(String [] Args){
try {
Scanner s = new Scanner(new File("your file.txt"));
StringTokenizer t = new StringTokenizer(s.nextLine());
Hashtable<Integer,Node> nodes = new Hashtable<Integer,Node>();
while(t.hasMoreTokens()){
int id = Integer.parseInt(t.nextToken());
nodes.put(id, new Node(id));
}
while(s.hasNextInt()){
Node e1 = nodes.get(s.nextInt());
Node e2 = nodes.get(s.nextInt());
e1.adjacent.add(e2);
e2.adjacent.add(e1);
}
\\now you can use the nodes Map above to retrieve nodes or to get a list:
List<Node> adjencyNodeList = new ArrayList(nodes.values());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class Node {
int id;
List<Node> adjacent = new ArrayList<Node>();
public Node(int id){
this.id = id;
}
}
Related
I am working to get the shortest reach in a graph problem in hackercode. I have designed a code and some testcases are fine whereas some testcases are terminated due to timeout.
Could you say where I need to optimize and please also comment about code style. I am looking for the ways to improve it.
Following is my code,
public class BFS {
public static class Graph {
public Node[] nodes;
Stack<Node> stack = new Stack<Node>();
public Graph(int size) {
nodes = new Node[size];
}
public void addEdge(int first, int second) {
Node nodeF = getNode(first);
if (nodeF == null) {
nodeF = new Node();
nodeF.nodeVal = first;
}
Node nodeS = getNode(second);
if (nodeS == null) {
nodeS = new Node();
nodeS.nodeVal = second;
}
nodeF.neighbours.add(nodeS);
nodes[first] = nodeF;
nodes[second] = nodeS;
}
public int[] shortestReach(int startId) { // 0 indexed
stack.push(getNode(startId));
int[] distance = new int[nodes.length];
Arrays.fill(distance, -1);
distance[startId] = 0;
while (!stack.isEmpty()) {
Node currentNode = stack.pop();
Set<Node> children = getChildren(currentNode);
for (Node node : children) {
distance[node.nodeVal] = distance[currentNode.nodeVal] + 6;
stack.add(node);
}
}
return distance;
}
public Set<Node> getChildren(Node givenNode) {
for (Node node : nodes) {
if (node == givenNode) {
return node.neighbours;
}
}
return null;
}
public Node getNode(int index) {
return nodes[index];
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int queries = scanner.nextInt();
for (int t = 0; t < queries; t++) {
// Create a graph of size n where each edge weight is 6:
Graph graph = new Graph(scanner.nextInt());
int m = scanner.nextInt();
// read and set edges
for (int i = 0; i < m; i++) {
int u = scanner.nextInt() - 1;
int v = scanner.nextInt() - 1;
// add each edge to the graph
graph.addEdge(u, v);
}
// Find shortest reach from node s
int startId = scanner.nextInt() - 1;
int[] distances = graph.shortestReach(startId);
for (int i = 0; i < distances.length; i++) {
if (i != startId) {
if (distances[i] == 0)
continue;
System.out.print(distances[i]);
System.out.print(" ");
}
}
System.out.println();
}
scanner.close();
}
}
class Node {
public int nodeVal;
public Set<Node> neighbours = new HashSet<Node>();
}
I read objects(Movies) from a file and i compare based on their likes. I want to get the median after every Movie insertion in the queue. In the code below there are :
Movie method compareTo
PQ insert and getMax methods with swim and sink
Main class
I'm creating both priority queues for higher and less objects than median, but i don't know how to dynamically calculate it. Every movie element is created with id, title, likes in this order.
public int compareTo(Movie m) {
if (this.likes == m.likes) {
return -this.title.compareTo(m.title);
} else if (this.likes > m.likes) {
return 1;
} else {
return -1;
}
}
public class PQ {
private Movie[] pq;
private int size;
public PQ(int capacity) {
if (capacity < 1) {
throw new IllegalArgumentException();
}
this.pq = new Movie[capacity + 1];
this.size = 0;
}
public void insert(Movie movie) {
if (this.size == this.pq.length - 1) {
throw new IllegalArgumentException();
}
if (movie == null) {
throw new IllegalArgumentException();
}
this.size++;
this.pq[this.size] = movie;
swim(this.size);
}
public void swim(int i) {
while (i > 1) {
int p = i / 2;
int result = this.pq[p].compareTo(this.pq[i]);
if (result <= 0)
return;
swap(i, p);
i = p;
}
}
public Movie Max() {
if (this.size == 0)
throw new IllegalArgumentException();
return this.pq[1];
}
public Movie getMax() {
if (this.size == 0)
throw new IllegalArgumentException();
Movie m = this.pq[1];
if (this.size > 1)
this.pq[1] = this.pq[this.size];
this.pq[this.size--] = null;
sink(1);
return m;
}
private void sink(int i) {
int left = 2 * i;
int right = left + 1;
int max = left;
while (left <= this.size) {
if (right <= this.size) {
max = this.pq[right].compareTo(this.pq[left]) < 0 ? right
: left;
}
if (this.pq[max].compareTo(this.pq[i]) >= 0)
return;
swap(i, max);
i = max;
left = 2 * i;
right = left + 1;
max = left;
}
}
private void swap(int i, int j) {
Movie tmp = pq[i];
pq[i] = pq[j];
pq[j] = tmp;
}
}
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Dynamic_Median {
public static void main(String[] args) {
BufferedReader br = null;
PQ higher_median = new PQ(4);
PQ less_median = new PQ(4);
Movie median = null;
try { // try to read the file
br = new BufferedReader(new FileReader("movies.txt"));
String line;
String title = "";
int id = 0;
int likes = 0;
while ((line = br.readLine()) != null) {
line = line.trim();
line = line.replaceAll("/t", "");
String[] tokens = line.split(" "); // store every token in an
// String array
id = Integer.parseInt(tokens[0]);
likes = Integer.parseInt(tokens[tokens.length - 1]);
for (int i = 1; i < tokens.length - 1; i++) {
title = title + " " + tokens[i];
}
title = "";
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ki esy re kopela mou teleftaia mera ths prothesmias thymithikes na rwthseis? :P
I am trying to implement an insert method of the Paricia trie data structure. I handled many cases but currently I am stuck in the case to differ these both cases:
case 1: Inserting the following 3 strings:
abaxyxlmn, abaxyz, aba
I could implement this case with the code below.
case 2: Inserting the following 3 strings:
abafg, abara, a
In the second case I do not know how to differ between the first and the second case since I need a clue to know when should I append the different substring ab to the childern edge to get abfa, abra. Finally, add ab as a child too to the node a. Please see the image below.
Code:
package patriciaTrie;
import java.util.ArrayList;
import java.util.Scanner;
public class Patricia {
private TrieNode nodeRoot;
private TrieNode nodeFirst;
// create a new node
public Patricia() {
nodeRoot = null;
}
// inserts a string into the trie
public void insert(String s) {
if (nodeRoot == null) {
nodeRoot = new TrieNode();
nodeFirst = new TrieNode(s);
nodeFirst.isWord = true;
nodeRoot.next.add(nodeFirst);
} else {
// nodeRoot.isWrod = false;
insert(nodeRoot, s);
}
}
private String checkEdgeString(ArrayList<TrieNode> history, String s) {
StringBuilder sb = new StringBuilder();
for (TrieNode nextNodeEdge : history) {
int len1 = nextNodeEdge.edge.length();
int len2 = s.length();
int len = Math.min(len1, len2);
for (int index = 0; index < len; index++) {
if (s.charAt(index) != nextNodeEdge.edge.charAt(index)) {
break;
} else {
char c = s.charAt(index);
sb.append(c);
}
}
}
return sb.toString();
}
private void insert(TrieNode node, String s) {
ArrayList<TrieNode> history = new ArrayList<TrieNode>();
for (TrieNode nextNodeEdge : node.getNext()) {
history.add(nextNodeEdge);
}
String communsubString = checkEdgeString(history, s);
System.out.println("commun String: " + communsubString);
if (!communsubString.isEmpty()) {
for (TrieNode nextNode : node.getNext()) {
if (nextNode.edge.startsWith(communsubString)) {
String substringSplit1 = nextNode.edge
.substring(communsubString.length());
String substringSplit2 = s.substring(communsubString
.length());
if (substringSplit1.isEmpty() && !substringSplit2.isEmpty()) {
// 1. case: aba, abaxyz
} else if (substringSplit2.isEmpty()
&& !substringSplit1.isEmpty()) {
// 2. case: abaxyz, aba
ArrayList<TrieNode> cacheNextNode = new ArrayList<TrieNode>();
System.out.println("node edge string is longer.");
if (nextNode.getNext() != null && !nextNode.getNext().isEmpty()) {
for (TrieNode subword : nextNode.getNext()) {
subword.edge = substringSplit1.concat(subword.edge); //This line
cacheNextNode.add(subword);
}
nextNode.getNext().clear();
nextNode.edge = communsubString;
nextNode.isWord = true;
TrieNode child = new TrieNode(substringSplit1);
child.isWord = true;
nextNode.next.add(child);
for(TrieNode node1 : cacheNextNode){
child.next.add(node1);
System.out.println("Test one");
}
cacheNextNode.clear();
}else{
nextNode.edge = communsubString;
TrieNode child = new TrieNode(substringSplit1);
child.isWord = true;
nextNode.next.add(child);
System.out.println("TEST");
}
} else if(substringSplit1.isEmpty() && substringSplit2.isEmpty()){
//3. case: aba and aba.
nextNode.isWord = true;
}else {
// 4. Case: abauwt and abaxyz
//if(nextNode.getNext().isEmpty())
}
break;
}
}
} else {
// There is no commun substring.
System.out.println("There is no commun substring");
TrieNode child = new TrieNode(s);
child.isWord = true;
node.next.add(child);
}
}
public static void main(String[] args) {
Patricia p = new Patricia();
Scanner s = new Scanner(System.in);
while (s.hasNext()) {
String op = s.next();
if (op.equals("INSERT")) {
p.insert(s.next());
}
}
}
class TrieNode {
ArrayList<TrieNode> next = new ArrayList<TrieNode>();
String edge;
boolean isWord;
// To create normal node.
TrieNode(String edge) {
this.edge = edge;
}
// To create the root node.
TrieNode() {
this.edge = "";
}
public ArrayList<TrieNode> getNext() {
return next;
}
public String getEdge() {
return edge;
}
}
}
When trying to solve this problem https://www.hackerrank.com/challenges/cut-the-tree
I was trying to always pick and cut a leaf and then combine its weight to the node that it connects.
I was using a PriorityQueue to store all the nodes, and using the size of their adjacent nodes as the priority. But when I'm trying some test case, it seems that the priority queue property is violated, which means that non-leaf nodes may appear before leaf nodes. Will PriorityQueue automatically update itself or should I call some function to update it. My temporary solution is to use a list to store all the leaves.
The following is my code:
public class Solution {
private static class Node implements Comparable<Node> {
int index;
int value;
Map<Integer, Node> adj;
public Node(int index, int value) {
this.index = index;
this.value = value;
this.adj = new HashMap<Integer, Node>();
}
#Override
public int compareTo(Node n) {
return adj.size() - n.adj.size();
}
}
public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
int total = 0;
int N = Integer.parseInt(br.readLine());
String[] strs = br.readLine().split(" ");
HashMap<Integer, Node> nodes = new HashMap<Integer, Node>();
for (int i = 0; i < N; i++) {
int value = Integer.parseInt(strs[i]);
nodes.put(i, new Node(i, value));
total += value;
}
for (int i = 0; i < N - 1; i++) {
strs = br.readLine().split(" ");
int n1 = Integer.parseInt(strs[0]) - 1;
int n2 = Integer.parseInt(strs[1]) - 1;
nodes.get(n1).adj.put(n2, nodes.get(n2));
nodes.get(n2).adj.put(n1, nodes.get(n1));
}
// PriorityQueue<Node> pq = new PriorityQueue<Node>(nodes.values());
// while (!pq.isEmpty()) {
// Node n = pq.poll();
// System.out.println(n.index + " " + n.adj.size());
// }
// NOTE: java's PriorityQueue doesn't support update, cannot use it
// LAME DESIGN. use a LinkedList instead
List<Node> leaves = new LinkedList<Node>();
for (Node node : nodes.values()) {
if (node.adj.size() == 1) {
leaves.add(node);
}
}
int minDiff = Integer.MAX_VALUE;
while (!leaves.isEmpty()) {
// get a leaf node
// Node leaf = pq.poll();
Node leaf = leaves.get(0);
leaves.remove(0);
if (leaf.adj.size() <= 0)// last node
break;
int diff = Math.abs((total - leaf.value) - leaf.value);
if (diff < minDiff)
minDiff = diff;
// combind leaf to it's connection
Node conn = null;
for (Node node : leaf.adj.values()) {
conn = node;
}
conn.value += leaf.value;
conn.adj.remove(leaf.index);
if (conn.adj.size() == 1)
leaves.add(conn);
nodes.remove(leaf.index);
}
System.out.println(minDiff);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Thanks.
The standard Java PriorityQueue does not support update. If you need to remove items, then you have to implement your own minHeap. Call heapify when you removed some items in the heap.
The implementation and explanation can be found here!
PrioirtyQueue does not have an implementation but LinkedHashMap does, they are removeEldestEntry.
According to documentation:
The removeEldestEntry(Map.Entry) method may be overridden to impose a policy for removing stale mappings automatically when new mappings are added to the map.
I am working on a undirected friendship graph which consists of students who are friends at a particular school. I want to get cliques(all connected subgraphs from the graph) using dfs. But for some reason my dfs is not working correctly.. Any suggestions on the algorithm or the code is appreciated
this is a sample graph created manually..
import java.util.LinkedHashMap;
public class DFS {
/**
* #param args
*/
class Node {
String personName, schoolName;
Node next;
public Node(String personName, String schoolName, Node next) {
this.personName = personName;
this.schoolName = schoolName;
this.next = next;
}
public String toString() {
return this.personName + " " + this.schoolName;
}
}
public Node[] build() {
Node[] graph = new Node[6];
for (int i = 0; i < graph.length; i++) {
Node temp = new Node(Integer.toString(i + 1), "MIT", null);
graph[i] = temp;
}
graph[0].next = new Node("2", "MIT", null);
graph[1].next = new Node("1", "MIT", null);
graph[1].next.next = new Node("3", "MIT", null);
graph[1].next.next.next = new Node("4", "MIT", null);
graph[2].next = new Node("2", "MIT", null);
graph[2].next.next = new Node("4", "MIT", null);
graph[3].next = new Node("3", "MIT", null);
graph[3].next.next = new Node("2", "MIT", null);
graph[4].next = new Node("6", "MIT", null);
graph[5].next = new Node("5", "MIT", null);
printGraph(graph);
return graph;
}
public void dfsDriver() {
Node[] graph = build();
LinkedHashMap<String, Integer> names = new LinkedHashMap<String, Integer>();
int count = 0;
for (int i = 0; i < graph.length; i++) {
if (graph[i] != null) {
names.put(graph[i].personName, count);
count++;
}
}
boolean[] visited = new boolean[graph.length];
for (int v = 0; v < visited.length; v++) {
visited[v] = false;
}
for (int i = 0; i < graph.length; i++) {
if (graph[i] != null) {
if (!visited[i]) {
System.out.println("Starting at " + graph[i].personName);
dfs(i, visited, names, graph);
}
}
}
}
private void dfs(int i, boolean[] visited, LinkedHashMap<String, Integer> names, Node[] subGraph) {
visited[i] = true;
for (Node e = subGraph[i].next; e != null; e = e.next) {
System.out.println("visiting " + e.personName);
int index = names.get(e.personName);
if (!visited[index]) {
dfs(index, visited, names, subGraph);
}
}
}
public void printGraph(Node[] list) {
System.out.println();
for (int i = 0; i < list.length; i++) {
if (list[i] != null) {
System.out.print(list[i]);
for (Node a = list[i].next; a != null; a = a.next) {
System.out.print(" " + a);
}
System.out.println();
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
DFS a = new DFS();
a.dfsDriver();
}
}
#1 : The graph creation is inefficient.
See this method in your code:
public Node[] build() {
There are 6 nodes that you wanted and look how many times are you calling "new Node". Its 6 + 10 times..Try to modify your data structures so that they suit to the inputs.
The current DS is :
class Node {
String personName, schoolName;
Node next;
Think about modifying this so that each node can "point" to multiple other nodes without creating new object for its frends every time.
#2 Confusing print statement in dfs method()
It should be like this:
private void dfs(int i, boolean[] visited,
LinkedHashMap<String, Integer> names, Node[] subGraph) {
visited[i] = true;
for (Node e = subGraph[i].next; e != null; e = e.next) {
int index = names.get(e.personName);
if (!visited[index]) {
System.out.println("visiting " + e.personName);
dfs(index, visited, names, subGraph);
}
}
}
#3: There is no mechanism to store the end results
You want all connected subgraphs from the main graph. However I dont see any provision to store/ mark the graph. You can modify the 2nd for loop inside public void dfsDriver() method so that it will create a new graph from the NEW nodes visited after each iteration.