import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Topological Sort Using DFS with few modifications
* NOte : applicable only for directed acyclic graphs
* @author Prateek
*
*/
class TOPOSort {
private int numVertices;
// Map containing nodes and their connected Nodes
private Map
<Integer, List
<Integer
>> adjList
;
// All nodes and their visit status
private Map
<Integer, Boolean
> vistedStatusList
;
public TOPOSort(int n) {
this.numVertices=n;
adjList
=new HashMap
<Integer, List
<Integer
>>(n
); vistedStatusList
=new HashMap
<Integer,Boolean
>(n
); }
/**
* Desc: adding edge between vertices
* @param src edge starts from here
* @param dest edge ends here
*/
private void addEdge(int src, int dest) {
// add node and set visit status as false (unvisited/ unexplored nodes)
vistedStatusList.put(src, false);
vistedStatusList.put(dest, false);
// get the adjacency list of a given node
List<Integer> list=adjList.get(src);
if(list==null) //if adjacency list is empty
list = new ArrayList<Integer>();
list.add(dest);
adjList.put(src,list);
}
///======== TOPOLOGICAL SORT ========/////////
// to keep track of ordering
private int currentLabel;
int[] sortedArray;
public void topologicalSort()
{
currentLabel=vistedStatusList.size()-1;
sortedArray=new int[numVertices];
Set
<Map.
Entry<Integer, Boolean
>> set
=vistedStatusList.
entrySet(); Iterator
<Map.
Entry<Integer, Boolean
>> iterator
=set.
iterator(); while(iterator.hasNext())
{
int key=node.getKey();
boolean isVisited=vistedStatusList.get(key);
if(!isVisited)
topologicalSortUtil(key); // Call DFS for a given node , if unvisited
}
// printing the topological sorted array
for(int i=0;i<sortedArray.length;i++)
{
if(sortedArray[i]!=0)
System.
out.
print(sortedArray
[i
]+"\t"); }
}
/**
* Procedure Similar to DFS, unwinds when deepest node is encountered
* @param vertex
*/
public void topologicalSortUtil(int vertex)
{
vistedStatusList.put(vertex,true);
List<Integer> list=adjList.get(vertex);
if(list!=null)
{
int size= list.size();
for(int i=0;i <size; ++i)
{
int adjNode=list.get(i);
boolean isVisited=vistedStatusList.get(adjNode);
if(!isVisited)
{
//System.out.println(adjNode + "\t");
topologicalSortUtil(adjNode);
}
}
}
/* for loop will end when the sink vertex is reached , that sink vertex is plucked and put in the array as per the currentLabel,
* which corresponds to its position in topological sort */
sortedArray[currentLabel]=vertex;
currentLabel--;
}
public static void main
(String[] args
) { int numVertices = 7;
TOPOSort g=new TOPOSort(numVertices);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(0, 5);
g.addEdge(1, 4);
g.addEdge(5, 2);
g.addEdge(3, 2);
g.addEdge(3, 5);
g.addEdge(3, 4);
g.addEdge(3, 6);
g.addEdge(6, 4);
g.addEdge(6, 1);
System.
out.
println("Topoogical Ordering is : "); g.topologicalSort();
}
}
CmltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0OwppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuSXRlcmF0b3I7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1wb3J0IGphdmEudXRpbC5NYXA7CmltcG9ydCBqYXZhLnV0aWwuU2V0OwoKLyoqCiAqIFRvcG9sb2dpY2FsIFNvcnQgVXNpbmcgREZTIHdpdGggZmV3IG1vZGlmaWNhdGlvbnMKICogTk90ZSA6IGFwcGxpY2FibGUgb25seSBmb3IgZGlyZWN0ZWQgYWN5Y2xpYyBncmFwaHMKICogQGF1dGhvciBQcmF0ZWVrCiAqCiAqLwpjbGFzcyBUT1BPU29ydCB7CgoJcHJpdmF0ZSBpbnQgbnVtVmVydGljZXM7CgkvLyBNYXAgY29udGFpbmluZyBub2RlcyBhbmQgdGhlaXIgY29ubmVjdGVkIE5vZGVzCglwcml2YXRlIE1hcDxJbnRlZ2VyLCBMaXN0PEludGVnZXI+PiBhZGpMaXN0OwoKCS8vIEFsbCBub2RlcyBhbmQgdGhlaXIgdmlzaXQgc3RhdHVzIAoJcHJpdmF0ZSBNYXA8SW50ZWdlciwgQm9vbGVhbj4gdmlzdGVkU3RhdHVzTGlzdDsKCglwdWJsaWMgVE9QT1NvcnQoaW50IG4pCXsKCQl0aGlzLm51bVZlcnRpY2VzPW47CgkJYWRqTGlzdD1uZXcgSGFzaE1hcDxJbnRlZ2VyLCBMaXN0PEludGVnZXI+PihuKTsKCQl2aXN0ZWRTdGF0dXNMaXN0PW5ldyBIYXNoTWFwPEludGVnZXIsQm9vbGVhbj4obik7Cgl9CgoJLyoqCgkgKiBEZXNjOiBhZGRpbmcgZWRnZSBiZXR3ZWVuIHZlcnRpY2VzCgkgKiBAcGFyYW0gc3JjIGVkZ2Ugc3RhcnRzIGZyb20gaGVyZQoJICogQHBhcmFtIGRlc3QgZWRnZSBlbmRzIGhlcmUKCSAqLwoJcHJpdmF0ZSB2b2lkIGFkZEVkZ2UoaW50IHNyYywgaW50IGRlc3QpIHsKCgkJLy8gYWRkIG5vZGUgYW5kIHNldCB2aXNpdCBzdGF0dXMgYXMgZmFsc2UgKHVudmlzaXRlZC8gdW5leHBsb3JlZCBub2RlcykKCQl2aXN0ZWRTdGF0dXNMaXN0LnB1dChzcmMsIGZhbHNlKTsKCQl2aXN0ZWRTdGF0dXNMaXN0LnB1dChkZXN0LCBmYWxzZSk7CgoJCS8vIGdldCB0aGUgYWRqYWNlbmN5IGxpc3Qgb2YgYSBnaXZlbiBub2RlIAoJCUxpc3Q8SW50ZWdlcj4gbGlzdD1hZGpMaXN0LmdldChzcmMpOwoKCgkJaWYobGlzdD09bnVsbCkgLy9pZiBhZGphY2VuY3kgbGlzdCBpcyBlbXB0eQoJCQlsaXN0ID0gbmV3IEFycmF5TGlzdDxJbnRlZ2VyPigpOwoKCQlsaXN0LmFkZChkZXN0KTsKCQlhZGpMaXN0LnB1dChzcmMsbGlzdCk7Cgl9CgoJLy8vPT09PT09PT0gVE9QT0xPR0lDQUwgU09SVCA9PT09PT09PS8vLy8vLy8vLwoJLy8gdG8ga2VlcCB0cmFjayBvZiBvcmRlcmluZwoJcHJpdmF0ZSBpbnQgY3VycmVudExhYmVsOwoJaW50W10gc29ydGVkQXJyYXk7CglwdWJsaWMgdm9pZCB0b3BvbG9naWNhbFNvcnQoKQoJewoKCQljdXJyZW50TGFiZWw9dmlzdGVkU3RhdHVzTGlzdC5zaXplKCktMTsKCQlzb3J0ZWRBcnJheT1uZXcgaW50W251bVZlcnRpY2VzXTsKCgkJU2V0PE1hcC5FbnRyeTxJbnRlZ2VyLCBCb29sZWFuPj4gc2V0PXZpc3RlZFN0YXR1c0xpc3QuZW50cnlTZXQoKTsKCQlJdGVyYXRvcjxNYXAuRW50cnk8SW50ZWdlciwgQm9vbGVhbj4+IGl0ZXJhdG9yPXNldC5pdGVyYXRvcigpOwoJCXdoaWxlKGl0ZXJhdG9yLmhhc05leHQoKSkKCQl7CgkJCU1hcC5FbnRyeTxJbnRlZ2VyLEJvb2xlYW4+IG5vZGU9IGl0ZXJhdG9yLm5leHQoKTsKCQkJaW50IGtleT1ub2RlLmdldEtleSgpOwoJCQlib29sZWFuIGlzVmlzaXRlZD12aXN0ZWRTdGF0dXNMaXN0LmdldChrZXkpOwoJCQlpZighaXNWaXNpdGVkKQoJCQkJdG9wb2xvZ2ljYWxTb3J0VXRpbChrZXkpOyAvLyBDYWxsIERGUyBmb3IgYSBnaXZlbiBub2RlICwgaWYgdW52aXNpdGVkCgkJfQoKCQkvLyBwcmludGluZyB0aGUgdG9wb2xvZ2ljYWwgc29ydGVkIGFycmF5CgkJZm9yKGludCBpPTA7aTxzb3J0ZWRBcnJheS5sZW5ndGg7aSsrKQoJCXsKCQkJaWYoc29ydGVkQXJyYXlbaV0hPTApCgkJCQlTeXN0ZW0ub3V0LnByaW50KHNvcnRlZEFycmF5W2ldKyJcdCIpOwoJCX0KCX0KCgoJLyoqCgkgKiBQcm9jZWR1cmUgU2ltaWxhciB0byBERlMsIHVud2luZHMgd2hlbiBkZWVwZXN0IG5vZGUgaXMgZW5jb3VudGVyZWQKCSAqIEBwYXJhbSB2ZXJ0ZXgKCSAqLwoJcHVibGljIHZvaWQgdG9wb2xvZ2ljYWxTb3J0VXRpbChpbnQgdmVydGV4KQoJewoJCXZpc3RlZFN0YXR1c0xpc3QucHV0KHZlcnRleCx0cnVlKTsKCQlMaXN0PEludGVnZXI+IGxpc3Q9YWRqTGlzdC5nZXQodmVydGV4KTsKCgkJaWYobGlzdCE9bnVsbCkKCQl7CgkJCWludCBzaXplPSBsaXN0LnNpemUoKTsKCQkJZm9yKGludCBpPTA7aSA8c2l6ZTsgKytpKQoJCQl7CgkJCQlpbnQgYWRqTm9kZT1saXN0LmdldChpKTsKCQkJCWJvb2xlYW4gaXNWaXNpdGVkPXZpc3RlZFN0YXR1c0xpc3QuZ2V0KGFkak5vZGUpOwoJCQkJaWYoIWlzVmlzaXRlZCkKCQkJCXsKCQkJCQkvL1N5c3RlbS5vdXQucHJpbnRsbihhZGpOb2RlICsgIlx0Iik7CgkJCQkJdG9wb2xvZ2ljYWxTb3J0VXRpbChhZGpOb2RlKTsKCQkJCX0KCQkJfQkKCQl9CgkJLyogZm9yIGxvb3Agd2lsbCBlbmQgd2hlbiB0aGUgc2luayB2ZXJ0ZXggaXMgcmVhY2hlZCAsIHRoYXQgc2luayB2ZXJ0ZXggaXMgcGx1Y2tlZCBhbmQgcHV0IGluIHRoZSBhcnJheSBhcyBwZXIgdGhlIGN1cnJlbnRMYWJlbCwgCgkJICogd2hpY2ggY29ycmVzcG9uZHMgdG8gaXRzIHBvc2l0aW9uIGluIHRvcG9sb2dpY2FsIHNvcnQgKi8KCQlzb3J0ZWRBcnJheVtjdXJyZW50TGFiZWxdPXZlcnRleDsKCQljdXJyZW50TGFiZWwtLTsKCgl9CgoJcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgewoJCWludCBudW1WZXJ0aWNlcyA9IDc7CgkJVE9QT1NvcnQgZz1uZXcgVE9QT1NvcnQobnVtVmVydGljZXMpOwoKCQlnLmFkZEVkZ2UoMCwgMSk7CgkJZy5hZGRFZGdlKDAsIDIpOwoJCWcuYWRkRWRnZSgwLCA1KTsKCQlnLmFkZEVkZ2UoMSwgNCk7CgkJZy5hZGRFZGdlKDUsIDIpOwoJCWcuYWRkRWRnZSgzLCAyKTsKCQlnLmFkZEVkZ2UoMywgNSk7CgkJZy5hZGRFZGdlKDMsIDQpOwoJCWcuYWRkRWRnZSgzLCA2KTsKCQlnLmFkZEVkZ2UoNiwgNCk7CgkJZy5hZGRFZGdlKDYsIDEpOwoKCQlTeXN0ZW0ub3V0LnByaW50bG4oIlRvcG9vZ2ljYWwgT3JkZXJpbmcgaXMgOiAiKTsKCQlnLnRvcG9sb2dpY2FsU29ydCgpOwoKCX0KfQo=