——选自《啊哈! 算法》第五章
Traversal
1
/ | \
2 3 ————5
|
4
1.深度优先遍历
1
/ |
2 3 ————5
|
4
图的邻接矩阵存储法(无向图):
– | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
1 | 0 | 1 | 1 | # | 1 |
2 | 1 | 0 | # | 1 | # |
3 | 1 | # | 0 | # | 1 |
4 | # | 1 | # | 0 | # |
5 | 1 | # | 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的举证来存储:
– | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
1 | 0 | 2 | # | # | 10 |
2 | # | 0 | 3 | # | 7 |
3 | 4 | # | 0 | 4 | # |
4 | # | # | # | 0 | 5 |
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;
}
选自《啊哈! 算法》第五章