`
sunlujing
  • 浏览: 177914 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

图的基本算法(DFS,BFS, topoSort,SCC)

阅读更多
由于要面试的缘故,在看算法导论的图算法一节,决定把基本的算法都用java代码实现出来。
1. 图的表示,使用链接表的形式。
class TreeNode{
	int nodeNum ; //节点编号
	TreeNode parent = null; //遍历时的父节点
	int dis = Integer.MAX_VALUE;// 距离源节点的路径
	int discoverTime =0; //在DFS遍历时发现的时间
	int finishTime =0;//DFS遍历时结束的时间
	Color color = Color.White;//初始时的颜色标记
	List<Integer> edges = new ArrayList<Integer>();//节点的边集合
	
	public TreeNode(int i) {
		nodeNum = i;
	}
	public int getNodeNum() {
		return nodeNum;
	}
	public void setNodeNum(int nodeNum) {
		this.nodeNum = nodeNum;
	}
	public TreeNode getParent() {
		return parent;
	}
	public void setParent(TreeNode parent) {
		this.parent = parent;
	}
	public int getDis() {
		return dis;
	}
	public void setDis(int dis) {
		this.dis = dis;
	}
	public int getDiscoverTime() {
		return discoverTime;
	}
	public void setDiscoverTime(int discoverTime) {
		this.discoverTime = discoverTime;
	}
	public int getFinishTime() {
		return finishTime;
	}
	public void setFinishTime(int finishTime) {
		this.finishTime = finishTime;
	}
}
 
2. 图的构建:
TreeNode[] heads = null;
final int NODENUM ;
public GraphicModelII(int nodeNum) {
   NODENUM = nodeNum;
   heads = new TreeNode[NODENUM+1];
   
   for(int i=1;i<=nodeNum;i++){
   heads[i] = new TreeNode(i);
   }
   }
public void addEdge(int src,int des){
   heads[src].edges.add(des);
   }
 
3. 广度优先搜索
   
public void BFS(int src){
   Queue<TreeNode> searchs = new LinkedList<TreeNode>();	    
   heads[src].color = Color.Gray;
   heads[src].dis= 0;
   searchs.add(heads[src]);
   while(!searchs.isEmpty()){
   TreeNode cur = searchs.poll();
   System.out.println("Node : "+cur.nodeNum);
   for(Integer des:cur.edges){
   TreeNode now  = heads[des];
   if(now.color == Color.White){
   now.color = Color.Gray;
   now.dis = cur.dis+1;
   now.parent = cur;
   searchs.add(now);
   }
   }
   cur.color = Color.Black;
   }
   
   }
 
 
4. 深度优先搜索
 public void DFS(){
   systemTime = 0;
   for(int i=1;i <=NODENUM;i++){
   TreeNode node = heads[i];
   if(node.color==Color.White){
   DFS_Visit(node);
   }
   }
   }
   public void DFS_Visit(TreeNode node){
   node.color = Color.Gray;
   systemTime++;
   node.discoverTime = systemTime; 
   for(Integer des:node.edges){
   TreeNode now = heads[des];
   if(now.color==Color.White){
   now.parent = node;
   DFS_Visit(now);
   }
   }
   node.color = Color.Black;
   systemTime++;
   node.finishTime = systemTime;
   topoSortUtil.push(node);
   System.out.println(node.nodeNum+"start:\t"+node.discoverTime+" end:\t"+node.finishTime);
   }
  
 
 
5. topo 排序:
topo 排序的算法
使用DFS来完成,对于每一个发现的节点,压入栈中
Stack<TreeNode> topoSortUtil = new Stack<TreeNode>();
对应DFS中 黄色标记代码
 public void topoSort(){
   topoSortUtil.clear();
   DFS();
   while(!topoSortUtil.isEmpty()){
   System.out.println(topoSortUtil.pop().nodeNum);
   }
   }
 
6. 求强连通分支SCC。
第一步 使用DFS算法,把每个节点遍历完成时写入到topoSortUtil 中,栈顶的元素是最后才遍历结束的节点。
第二步,求原图G的转置, 把原图中 u -v的边 变为 v-u.
见reverTopo 函数,遍历之后的图用heads_reverse 表示
第三步  使用DFS算法,求SCC。需要注意的是,在原始的DFS中
public void DFS(){
   systemTime = 0;
   for(int i=1;i <=NODENUM;i++){
 
   TreeNode node = heads[i];
   if(node.color==Color.White){
   DFS_Visit(node);
   }
   }
   }
for 循环 的节点顺序无要求,但是在求SCC时,需要使用topoSortUtil,最晚结束遍历的元素作为第二次遍历的第一个元素,并依此类推。
  
 public void SCC(){
  
   DFS();
   List<TreeNode> scc = new ArrayList<TreeNode>();
   reverTopo();
   while(!topoSortUtil.isEmpty()){
  TreeNode cur = heads_reverse[topoSortUtil.pop().nodeNum];
  if(cur.color==Color.White){
  DFS_Visit_Scc(cur,scc);
   }
  for(TreeNode node:scc){
  System.out.print(node.nodeNum);
  }
  System.out.println();
  scc.clear();
   }
   }
   
   public void DFS_Visit_Scc(TreeNode node,List<TreeNode> scc){
   node.color = Color.Gray;
   systemTime++;
   node.discoverTime = systemTime; 
   for(Integer des:node.edges){
   TreeNode now = heads_reverse[des];
   if(now.color==Color.White){
   now.parent = node;
   DFS_Visit_Scc(now,scc);
   }
   }
   node.color = Color.Black;
   systemTime++;
   node.finishTime = systemTime;
   scc.add(node);
   }
   
   private void reverTopo(){
   for(int i=1;i <=NODENUM;i++){
   TreeNode node = heads[i];
   int src = node.nodeNum;
   for(Integer des:node.edges){
   TreeNode reverNode = heads_reverse[des];
   reverNode.edges.add(src);
   }
   }
   }
 
完整代码
package graphic;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;

public class GraphicModelII {
	TreeNode[] heads = null;
	final int NODENUM ;
	static int  systemTime = 0;
	Stack<TreeNode> topoSortUtil = new Stack<TreeNode>();
	TreeNode[] heads_reverse = null;
	
	
	public GraphicModelII(int nodeNum) {
		   NODENUM = nodeNum;
		   heads = new TreeNode[NODENUM+1];
		   heads_reverse =new TreeNode[NODENUM+1];
		   
		   for(int i=1;i<=nodeNum;i++){
			   heads[i] = new TreeNode(i);
			   heads_reverse[i] = new TreeNode(i);
		   }
	   }
	   public void addEdge(int src,int des){
		   heads[src].edges.add(des);
	   }
	   
	   
	   public void BFS(int src){
		   Queue<TreeNode> searchs = new LinkedList<TreeNode>();
		   
		   heads[src].color = Color.Gray;
		   heads[src].dis= 0;
		   searchs.add(heads[src]);
		   while(!searchs.isEmpty()){
			   TreeNode cur = searchs.poll();
			   System.out.println("Node : "+cur.nodeNum);
			   for(Integer des:cur.edges){
				   TreeNode now  = heads[des];
				   if(now.color == Color.White){
					   now.color = Color.Gray;
					   now.dis = cur.dis+1;
					   now.parent = cur;
					   searchs.add(now);
				   }
			   }
			   cur.color = Color.Black;
		   }
		   
	   }
	   
	   public void DFS(){
		   systemTime = 0;
		   for(int i=1;i <=NODENUM;i++){
			
			   TreeNode node = heads[i];
			   if(node.color==Color.White){
				   DFS_Visit(node);
			   }
		   }
	   }
	   public void DFS_Visit(TreeNode node){
		   node.color = Color.Gray;
		   systemTime++;
		   node.discoverTime = systemTime; 
		   for(Integer des:node.edges){
			   TreeNode now = heads[des];
			   if(now.color==Color.White){
				   now.parent = node;
				   DFS_Visit(now);
			   }
		   }
		   node.color = Color.Black;
		   systemTime++;
		   node.finishTime = systemTime;
		   topoSortUtil.push(node);
		   System.out.println(node.nodeNum+"start:\t"+node.discoverTime+" end:\t"+node.finishTime);
	   }
	   
	   public void topoSort(){
		   topoSortUtil.clear();
		   DFS();
		   while(!topoSortUtil.isEmpty()){
			   System.out.println(topoSortUtil.pop().nodeNum);
		   }
	   }
	   
	   public void SCC(){
		  
		   DFS();
		   List<TreeNode> scc = new ArrayList<TreeNode>();
		   reverTopo();
		   while(!topoSortUtil.isEmpty()){
			  TreeNode cur = heads_reverse[topoSortUtil.pop().nodeNum];
			  if(cur.color==Color.White){
				  DFS_Visit_Scc(cur,scc);
			   }
			  for(TreeNode node:scc){
				  System.out.print(node.nodeNum);
			  }
			  System.out.println();
			  scc.clear();
		   }
	   }
	   
	   public void DFS_Visit_Scc(TreeNode node,List<TreeNode> scc){
		   node.color = Color.Gray;
		   systemTime++;
		   node.discoverTime = systemTime; 
		   for(Integer des:node.edges){
			   TreeNode now = heads_reverse[des];
			   if(now.color==Color.White){
				   now.parent = node;
				   DFS_Visit_Scc(now,scc);
			   }
		   }
		   node.color = Color.Black;
		   systemTime++;
		   node.finishTime = systemTime;
		   scc.add(node);
	   }
	   
	   private void reverTopo(){
		   for(int i=1;i <=NODENUM;i++){
			   TreeNode node = heads[i];
			   int src = node.nodeNum;
			   for(Integer des:node.edges){
				   TreeNode reverNode = heads_reverse[des];
				   reverNode.edges.add(src);
			   }
		   }
	   }
	   
	   public static void main(String[] args) {
//		   GraphicModelII graph = new GraphicModelII(5);
//		   graph.addEdge(1, 2);
//		   graph.addEdge(1, 5);
//		   graph.addEdge(2, 1);
//		   graph.addEdge(2, 5);
//		   graph.addEdge(2, 4);
//		   graph.addEdge(2, 3);
//		   graph.addEdge(3, 2);
//		   graph.addEdge(3, 4);
//		   graph.addEdge(4, 2);
//		   graph.addEdge(4, 5);
//		   graph.addEdge(5, 4);
//		   graph.addEdge(5, 2);
//		   graph.addEdge(5, 1);
		  // graph.BFS(1);
		   //graph.DFS();
//		   GraphicModelII graph = new GraphicModelII(9);
//		   graph.addEdge(1, 2);
//		   graph.addEdge(1, 8);
//		   graph.addEdge(2, 3);
//		   graph.addEdge(2, 8);
//		   graph.addEdge(3, 6);
//		   graph.addEdge(4, 3);
//		   graph.addEdge(4, 5);
//		   graph.addEdge(5, 6);
//		   graph.addEdge(7, 8);
//		   graph.topoSort();
		   
		   //test scc
		   GraphicModelII graph = new GraphicModelII(8);
		   graph.addEdge(1, 2);
		   graph.addEdge(2, 3);
		   graph.addEdge(3, 4);
		   graph.addEdge(4, 3);
		   graph.addEdge(2, 5);
		   graph.addEdge(2, 6);
		   graph.addEdge(3, 7);
		   graph.addEdge(4, 8);
		   graph.addEdge(5, 1);
		   graph.addEdge(5, 6);
		   graph.addEdge(6, 7);
		   graph.addEdge(7, 6);
		   graph.addEdge(7,8);
		   graph.addEdge(8,8);
		   //graph.topoSort();
		   graph.SCC();
	   }
}
class TreeNode{
	int nodeNum ;
	TreeNode parent = null;
	int dis = Integer.MAX_VALUE;
	int discoverTime =0;
	int finishTime =0;
	Color color = Color.White;
	List<Integer> edges = new ArrayList<Integer>();
	
	public TreeNode(int i) {
		nodeNum = i;
	}
	public int getNodeNum() {
		return nodeNum;
	}
	public void setNodeNum(int nodeNum) {
		this.nodeNum = nodeNum;
	}
	public TreeNode getParent() {
		return parent;
	}
	public void setParent(TreeNode parent) {
		this.parent = parent;
	}
	public int getDis() {
		return dis;
	}
	public void setDis(int dis) {
		this.dis = dis;
	}
	public int getDiscoverTime() {
		return discoverTime;
	}
	public void setDiscoverTime(int discoverTime) {
		this.discoverTime = discoverTime;
	}
	public int getFinishTime() {
		return finishTime;
	}
	public void setFinishTime(int finishTime) {
		this.finishTime = finishTime;
	}
	
	
}
 
2
2
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics