您的位置:首页 > 其它

图的遍历 (深度优先 广度优先)

2016-05-11 16:44 232 查看
——选自《啊哈! 算法》第五章

Traversal

1
/    |    \
2    3 ————5
|
4


1.深度优先遍历

1
/    |
2    3 ————5
|
4


图的邻接矩阵存储法(无向图):

-12345
1011#1
210#1#
31#0#1
4#1#0#
51#1#0
第i行第j列就是顶点i到j是否有边,1表示有边,#表示无边,自己到自己设为0.

无向图:沿主对角线对称。

深度优先遍历:

#include<stdio.h>
int book[101], sum, n, e[101][101];
void dfs(int cur){
int i;
printf("%d ",cur);
sum++;
if(sum == n) return;
for(i = 1; i<= n; i++){
if (e[cur][i] == 1 && book[i] == 0){
book[i] = 1;

dfs(i);
}
}
return ;
}

int main(){
int i,j,m,a,b;
scanf("%d %d", &n, &m);
//初始化二维矩阵
for(i=1;i<=m;i++){
scanf("%d %d",&a,&b);
e[a][b] = 1;
e[b][a] = 1; //无向图
}
//从1号城市出发
book[1] = 1;
dfs(1);
getchar();
return 0;
}


2.使用广度优先遍历:

1
/    |    \
2    3     5
|
4

// 首先以一个未被访问过的顶点作为起始顶点,然后将与该顶点相邻且未访问过的顶点放入到队列中

#include <stdio.h>
int main(){
int book[101] = {0},e[101][101]={0};
int n,m; //n:顶点数, m:边的条数
int i,j,a,b;
int que[101];
scanf("%d %d",&n,&m);
for(i = 1;i<=n;i++){
for(j = 1; j<=n; j++){
if(i == j) e[i][i] = 0;
else e[i][j] = 99999999;
}

}
for(i = 1;i <=m; i++){
scanf("%d %d",&a,&b);
e[a][b] = 1;
e[b][a] = 1;
}

// 队列初始化
head = 1;
tail = 1;
que[tail] = 1; // 从1号顶点出发
tail++;
book[1] = 1; // 标记1号顶点已访问
while(head < tail){
for(j = 1; j <= n; j++){
cur = que[head];
if(e[cur][j] == 1 && book[j] == 0){
sum++;
book[j] == 1;
que[tail] == j;
tail++;
}
if(tail > n){
break;
}
}
head++;
}

for(i=1;i<tail;i++){
printf("%d ",que[i]);
}
getchar();
return 0;

}


3.城市地图——有向图的深度优先遍历

5 8
1 2 2
1 5 10
2 3 3
2 5 7
3 1 4
3 4 4
4 5 5
5 3 3
第一行的5:5个城市 8:8条公路
2-9行: a b c : 从城市a 到 城市b 的距离为c(不表示从b到a的距离也为c)


从5*5的举证来存储:

-12345
102##10
2#03#7
34#04#
4###05
5##3#0
深度优先寻找从1号城市到5号城市的最短路径:

#include<stdio.h>
int min = 99999999, book[101], n, e[101][101];
// cur 是当前所在的城市编号,dis是当前已经走过的路程
void dfs(int cur, int dis){
int j;
if(dis > min){
return ;
}
if(cur == n){
if(dis < min){
min = dis;
}
return ;
}

for(j = 1; j<= n; j++){
if(e[cur][j]!= 99999999 && book[j] == 0){
book[j] = 1;
dfs(j, dis+e[cur][j]);
book[j] = 0;
}
}
return ;
}

int main(){
int i,j,m,a,b,c;
scanf("%d %d",&n,&m);
for(i = 1; i<=n; i++){
for(j = 1;j<=n;j++){
if(i == j) e[i][j] =0;
else e[i][j] = 99999999;
}
}

for(i=1; i<=m;i++){
scanf("%d %d %d", &a, &b, &c);
e[a][b] = c;
}

book[1] = 1;
dfs(1,0); // 1:当前所在城市编号 0:当前已经走过的路程
printf("最短路径为%d",min);

getchar();
return 0;
}


4.最少转机——图的广度优先遍历

5 7 1 5  //5个城市 7条航线 1: 起点城市 5:终点城市
1 2
1 3
2 3
2 4
3 4
3 5
4 5


利用广度优先搜索寻找城市1到城市5的最短路径:

#include <stdio.h>
struct node{
int x; // 城市编号
int s; // 转机次数
};
int main(){
struct note que[2501];
int head, tail;
int book[2501];
int e[51][51];
int cur,i;
int start=1, end=5;
//输入数据...

//BFS
//初始化队列
head = 1;
tail = 1;
que[tail].x = start;
que[tail].s = 0;
book[1] = 1;
tail++;
while(head < tail){
cur = que[head].x;
for(i = 1; i <= n; i++){
if(e[cur][i] != 99999999 && book[i] == 0){
book[i] = 1;
que[tail].x = i;
que[tail].s = que[head].s + 1;
tail++;
}
if(que[tail-1].x == end){
flag = 1;
break;
}
}

if(flag == 1){
break;
}
head++;
}

//输出结果
printf("%d", que[tail-1].s);
getchar();
return 0;

}


选自《啊哈! 算法》第五章
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: