无向图的邻接矩阵 -- DFS - 深度优先遍历
逝去的日子: 2012/11/01
回想当年在学校学数据结构时,很多算法都没有搞得太明白,可能那时太不用心了,也可能是自己理解的太慢了.现在重新拿起数据结构的一本书决心好好温习一遍.
发现这里对其有动画的演示:
http://www.tyut.edu.cn/kecheng1/site01/suanfayanshi/default.asp
记得学校时,好像学校机房里也有一个DOS下的动画演示.
这个理解含义就比较简单了,回想当年在学校学树\图这些算法时,怎么就想不明白呢?
DFS可以用在迷宫这类的题,因是贪心算法之类的.
如下的图1,如果我们把它看成是有层次的(相对于广度优先算法),
从0开始,找下一层就是 1,2,3的节点,深度就是深入进去啦,如下一点1,
1下面有节点4,4下面有2,5,再从其中一个,如2,
2下面有0,5,0已经遍历过了,所以再从5开始,
5下面有3,4,4已经遍历过了,所以下一节点3,
3下面节点有0,0也遍历过了,回到了起点
遍历完了.
当然图1没有一个是像树那样的叶子节点,没有说到回逆,
假如4和2,5节点的连接是没有的,那么遍历到1时,
1下面有4,4没有其它连接节点了,回到1,
1没有其它的还没有遍历的节点了,再回到0
0下还有2,3没有遍历,从2 开始.....
后面的就一致了.
图1(一个连通分量)
图2 (二个连通分量)
#include<stdio.h>
#include<stdlib.h>
//一个6个点的邻接矩阵
#define COUNT_POINTS 6
/* //图1的矩阵
int arr_point[COUNT_POINTS][COUNT_POINTS]={
{0,1,1,1,0,0},
{1,0,0,0,1,0},
{1,0,0,0,1,1},
{1,0,0,0,0,1},
{0,1,1,0,0,1},
{0,0,1,1,1,0}
};
*/
//图2的矩阵
int arr_point[COUNT_POINTS][COUNT_POINTS]={
{0,1,1,0,0,0},
{1,0,0,0,1,0},
{1,0,0,0,1,0},
{0,0,0,0,0,1},
{0,1,1,0,0,0},
{0,0,0,1,0,0}
};
//记录COUNT_POINTS个点是否遍历过,如果为0表示没有,1表示遍历过. 如 points_visited[1] 表示第2个点是否被遍历过了
int points_visited[COUNT_POINTS] = {0};
/*
*深度优先遍历
*给定一个点开始遍历,
*i表示第几个点
*/
static void DFS(int i){
int k;
//打印遍历到的点
printf("point:%d\n",i);
if(i>=0 && i<COUNT_POINTS){
points_visited[i] = 1;
for(k = 0; k < COUNT_POINTS; k++){
//如果一个点没有被遍历过:points_visited[k] !=1,并且与当前点是相连的arr_point[i][k] == 1,就进入下一层
if((k != i) && (points_visited[k] !=1) && (arr_point[i][k] == 1)){
DFS(k);
}
}
}
}
int main(int argv,char *argc[])
{
int k;
//如果一个点就遍历完了,就是一个连通图
for(k=0;k<COUNT_POINTS;k++)
if(points_visited[k] == 0){
printf("connected component\n");
DFS(k);
}
return 0;
}
图1的结果:
hello2012@ubuntu:~/CookBookC$ sudo gcc -g BFS.c -o BFS.out
hello2012@ubuntu:~/CookBookC$ ./BFS.out
connected component:
point:0
point:1
point:4
point:2
point:5
point:3
图2的结果:
hello2012@ubuntu:~/CookBookC$ sudo gcc -g BFS.c -o BFS.out
hello2012@ubuntu:~/CookBookC$ ./BFS.out
connected component
point:0
point:1
point:4
point:2
connected component
point:3
point:5