/*
* Copyright (C) 2016 Naman Dwivedi
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package com.naman14.algovisualizer.algorithm.graph;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Stack;
public class Digraph {
private Map<Integer, List<Integer>> neighbors = new HashMap<Integer, List<Integer>>();
public double[][] directed_array;
public String toString() {
StringBuffer s = new StringBuffer();
for (int v : neighbors.keySet()) s.append("\n " + v + " -> " + neighbors.get(v));
return s.toString();
}
public void add(int vertex) {
if (neighbors.containsKey(vertex)) return;
neighbors.put(vertex, new ArrayList<Integer>());
}
public boolean contains(int vertex) {
return neighbors.containsKey(vertex);
}
public void add(int from, int to) {
this.add(from);
this.add(to);
neighbors.get(from).add(to);
}
public void remove(int from, int to) {
if (!(this.contains(from) && this.contains(to)))
throw new IllegalArgumentException("Nonexistent vertex");
neighbors.get(from).remove(to);
}
public int getRoot() {
return topSort().get(0);
}
public boolean exists(int from) {
return neighbors.get(from) != null && neighbors.get(from).size() != 0;
}
public boolean edgeExists(int from, int to) {
return neighbors.get(from)!=null && neighbors.get(from).size()!=0 && neighbors.get(from).contains(to);
}
public List<Integer> getNeighbours(int node) {
return neighbors.get(node);
}
public int size() {
return neighbors.size();
}
public void setDirectedArray(double[][] directed_array) {
this.directed_array = directed_array;
}
public Map<Integer, Integer> outDegree() {
Map<Integer, Integer> result = new HashMap<Integer, Integer>();
for (Integer v : neighbors.keySet()) result.put(v, neighbors.get(v).size());
return result;
}
public Map<Integer, Integer> inDegree() {
Map<Integer, Integer> result = new HashMap<Integer, Integer>();
for (Integer v : neighbors.keySet()) result.put(v, 0); // All in-degrees are 0
for (Integer from : neighbors.keySet()) {
for (Integer to : neighbors.get(from)) {
result.put(to, result.get(to) + 1); // Increment in-degree
}
}
return result;
}
public List<Integer> topSort() {
Map<Integer, Integer> degree = inDegree();
Stack<Integer> zeroVerts = new Stack<Integer>();
for (Integer v : degree.keySet()) {
if (degree.get(v) == 0) zeroVerts.push(v);
}
List<Integer> result = new ArrayList<Integer>();
while (!zeroVerts.isEmpty()) {
Integer v = zeroVerts.pop();
result.add(v);
for (Integer neighbor : neighbors.get(v)) {
degree.put(neighbor, degree.get(neighbor) - 1);
if (degree.get(neighbor) == 0) zeroVerts.push(neighbor);
}
}
if (result.size() != neighbors.size()) return null;
return result;
}
public boolean isAcyclic() {
return topSort() != null;
}
public Map bfsDistance(Integer start) {
Map<Integer, Integer> distance = new HashMap<Integer, Integer>();
for (Integer v : neighbors.keySet()) distance.put(v, null);
distance.put(start, 0);
Queue<Integer> queue = new LinkedList<Integer>();
queue.offer(start);
while (!queue.isEmpty()) {
Integer v = queue.remove();
int vDist = distance.get(v);
for (Integer neighbor : neighbors.get(v)) {
if (distance.get(neighbor) != null) continue;
distance.put(neighbor, vDist + 1);
queue.offer(neighbor);
}
}
return distance;
}
}