最近项目中需要研究了一下有向图的环路问题。一个IT企业中有成千上万个应用,各个应用之间都是相互依赖的,一个用户请求进来后,会调用一系列应用,比如A调B、B调C、C调D等。这样所有的应用形成一个有向图,那么如果这个有向图中出现了环路,就悲剧了,用户的请求如果进入这个环路,那么他永远也得不到响应。所以就有需要去判断这个应用组成的有向图中是否含有环路,如果有就要打印出所有的环路(打印的时候按照从小到大的顺序打印)
上面就是我前几天在阿里做的一道代码题,半小时,不是原题但是原理一样,很悲催自己什么都没有写出来,自己春招准备的少,还没有时间回顾之前的数据结构,拿道题的时候根本没有往数据结构那几个方面上去想,过后才想到这不就是在一个图里面找环路,采用广度优先遍历的算法,加上排序(我这里采用快速排序算法)实现,实现代码如下(阿里的编程题,需要将输入转成二维数组,这里就不转了,直接就是二维数组),这里代码如下
import java.util.Stack;
public class Main{
static Stack trace=new Stack();
static boolean hasCycle=false;
static final int POINT_NUM=9;
static int[][] edge={
{0,0,0,0,0,0,0,0,1},
{0,0,0,1,1,0,0,0,0},
{1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,0},
{1,0,0,0,0,0,0,0,0},
{0,0,1,0,0,0,1,0,0},
{0,0,0,0,0,1,0,0,0}} ;
public static void main(String[] args){
}
public static void findcle(int point){
int j=0;
if((j=trace.indexOf(point))!=-1)
{
hasCycle=true;
int[] data=new int[trace.size()-j];
int i=0;
while(j<trace.size()){
data[i]=trace.get(j);
i++;
j++;
}
quickSort(data,0,data.length-1);
for(int m=0;m<data.length;m++)
System.out.print(data[m]+" ");
System.out.print("\n");
}
trace.push(point);
for(int i=0;i<POINT_NUM;i++)
if(edge[point][i]==1)
findcle(i);
trace.pop();
}
public static void quickSort(int[] data,int left,int right){
if(left<right){
int value=data[left];
int i=left;
int j=right;
while(i<j){
while(i<j && data[j]>=value)j--;
data[i]=data[j];
while(i<j && data[i]<=value)i++;
data[j]=data[i];
}
data[i]=value;
quickSort(data,left,i-1);
quickSort(data,i+1,right);
}
}
}
</pre>
总结一下方法: 主要用到的是广度优先遍历和快速排序
广度优先遍历:就是从头节点开始向下遍历,每路过一个节点就把它标记为已访问,一层一层访问过去。
深度优先遍历:从头节点开始,直接向下访问,访问不了,才跳回上一层访问
快排:选一个基本点,把数组分成两半,左边比他小,右边比他大,然后一直循环下去分,知道分到一个的时候就已经排好序了
归并排序:先分,合起来的时候再排序,和快排相反。
要是在当时写出来多好。。。。。