5.1 深度搜索,广度搜索
如果我没记错的话,第四章第一部分就就这两个搜索进行了解释并写过代码了,所以我们就快速地写一遍过掉吧!
深度搜索
static int[][] e=new int[50][50];
static int[] book=new int[50];
static int n,m,sum=0;
public void dfs(int i){
System.out.println(i);
book[i]=1;
sum++;
if(sum==n)
return;
for(int j=1;j<=n;j++){
if(e[i][j]==1&&book[j]==0) {
dfs(j);
}
}
return;
}
public static void main(String[] args){
dfs test=new dfs();
Scanner sc=new Scanner(System.in);
System.out.println("请输入矩阵的长和宽:");
m=sc.nextInt();
n=sc.nextInt();
System.out.println("请输入哪些点相连(两两一行)");
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(i==j)
e[i][j]=0;
else
e[i][j]=99999;
}
}
for(int i=1;i<=m;i++){
int a1=sc.nextInt();
int a2=sc.nextInt();
e[a1][a2]=1;
e[a2][a1]=1;
}
book[1]=1;
test.dfs(1);
}
广度搜索
public static void main(String[] args){
int[][] e=new int[50][50];
int[] book=new int[50];
int[] point=new int[50];
int n,m,head,tail;
bfs test=new bfs();
Scanner sc=new Scanner(System.in);
System.out.println("请输入矩阵的长和宽:");
m=sc.nextInt();
n=sc.nextInt();
System.out.println("请输入哪些点相连(两两一行)");
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(i==j)
e[i][j]=0;
else
e[i][j]=99999;
}
}
for(int i=1;i<=m;i++){
int a1=sc.nextInt();
int a2=sc.nextInt();
e[a1][a2]=1;
e[a2][a1]=1;
}
head=1;
tail=1;
point[tail]=1;
book[tail]=1;
tail++;
while(head<tail){
for(int i=1;i<=m;i++){
if(e[head][i]==1&&book[i]==0){
book[i]=1;
point[tail]=i;
tail++;
}
}
head++;
}
for(int i=1;i<=m;i++)
System.out.println(point[i]);
}
接下来小哼又要给自己出难题啦~我发现小哼真的变成男生了耶(奇怪的关注点)说难好像也没有多难,只是把上面两个算法运用到图当中。
5.2 图的深度优先搜索
static int[][] e=new int[50][50];
static int[] book=new int[50];
static int n,m,min=99999;
public void dfsdiagram(int i,int distance){
if(distance>min)
return;
if(i==n){
if(distance<min) {
min = distance;
book[n] =0;
}
return;
}
for(int j=1;j<=n;j++){
if(e[i][j]!=99999&&book[j]==0) {
book[j]=1;
dfsdiagram(j,distance+e[i][j]);
book[j]=0;
}
}
return;
}
public static void main(String[] args){
dfsdiagram test=new dfsdiagram();
Scanner sc=new Scanner(System.in);
System.out.println("请输入地图的点和边:");
n=sc.nextInt(); //点
m=sc.nextInt(); //边
System.out.println("请输入有向边的起点、终点和权值");
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)
e[i][j]=0;
else
e[i][j]=99999;
}
}
for(int i=1;i<=m;i++){
int a1=sc.nextInt();
int a2=sc.nextInt();
int dis=sc.nextInt();
e[a1][a2]=dis;
}
book[1]=1;
test.dfsdiagram(1,0);
System.out.println(min);
}
这里书上的代码有一点问题,在到达终点return前理应取消对终点的标记,不然的话只能更新一次最小值。
5.3 图的广度优先遍历
其实我觉得这里突然又采用无向图有一些奇怪,有向图不好吗?是否是广度优先算法的局限?那就偏要试试有向图了!还是用队列的方法。
好吧我回来了,我承认我看题有点马虎,广度优先搜索无法就权值进行判断,所以是不是有向图确实没那么重要。
static class point{
int place;//站点
int turn; //转机次数
}
public static void main(String[] args){
int[][] e=new int[50][50];
int[] book=new int[50];
point[] points=new point[50];
int n,m,sp,ep,head,tail,flag=0,sum;
bfsdiagram test=new bfsdiagram();
Scanner sc=new Scanner(System.in);
System.out.println("请输入地图的点和边:");
n=sc.nextInt();//点
m=sc.nextInt();//边
System.out.println("请输入地图的起点和终点");
sp=sc.nextInt();
ep=sc.nextInt();
System.out.println("请输入有向边的起点、终点");
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)
e[i][j]=0;
else
e[i][j]=99999;
}
}
for(int i=1;i<=m;i++){
int a1=sc.nextInt();
int a2=sc.nextInt();
e[a1][a2]=1;
}
head=1;
tail=1;
points[tail]=new point();
points[tail].place=1;
points[tail].turn=0;
book[tail]=1;
tail++;
while(head<tail){
for(int i=1;i<=n;i++){
if(e[head][i]==1&&book[i]==0){
book[i]=1;
points[tail]=new point();
points[tail].place=i;
points[tail].turn=points[head].turn+1;
tail++;
if(i==ep){ //如果下一站是终点站,直接跳出循环
flag=1;
break;
}
}
}
if(flag==1)
break;
head++;
}
System.out.println("总共转机"+points[tail-1].turn+"次");
}
/*
1 2
1 3
2 3
2 4
3 4
3 5
4 5
*/
这里我刚开始尝试不添加point的class,但是,光凭借head和tail是无法得出转机次数的,他的队列标记不代表转机次数,而代表每一次转机的可能性,所以,这里的point类的turn变量确确实实不可少。
简单的一章!期待接下来的奇妙算法吧?