- 图:图G是一个有序二元组(V,E),其中V称为顶集(Vertices Set),E称为边集(Edges set),E与V不相交。它们亦可写成V(G)和E(G)。其中,顶集的元素被称为顶点(Vertex),边集的元素被称为边(edge)。图可分为有向图和无向图,这里以无向图为例。(图的定义)
- 图的表示:邻接表和邻接矩阵,对于稀疏矩阵邻接表所占有的空间远小于邻接矩阵。(图的两种表示方法)
- 深度优先:从给定点出发,按照某种搜索逻辑,一直往前走,直至进入死胡同。此时,将会回退到最近一个可通行的点,并从该点出发进行深度遍历,直至所有点均被访问。与广度优先相比,深度优先更有一条路走到黑的勇气。
- 广度优先:从给定点出发,按照某种搜索逻辑,依次访问距离最近的所有点。此时完成了第一次搜索,接下来以同样的方法进行下一次搜索,直至所有的点均被访问。与深度优先相比,广度优先显得更加的谨慎小心。
- 代码
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTICES 52
void initVisited();
int getPos(char x, int lenNow);
/*地图(二维表),取值为1表示两个点有关联*/
int graph[MAX_VERTICES][MAX_VERTICES];
/*顶点数*/
int vertices;
/*访问数组*/
int visited[MAX_VERTICES];
/*点集*/
char vertex[MAX_VERTICES];
/*创建地图*/
void creategraph()
{
int i, j = 0, edges, x, y;
printf("顶点数、边数:");
scanf("%d %d", &vertices, &edges);
/*接收多余的换行符,防止后面数据读取错误*/
getchar();
printf("%d对关联的点:\n", edges);
for (i = 0;i < edges;i++)
{
char from, to;
scanf("%c %c", &from, &to);
getchar();
/*获取该顶点在vertex的位置*/
x = getPos(from, j);
/*与vertex当前长度相等,说明该顶点不存在vertex中*/
if (x == j)
{
vertex[j++] = from;
}
y = getPos(to, j);
if (y == j)
{
vertex[j++] = to;
}
/*根据无向图的对称性,给关联两点对应的坐标赋值*/
graph[x][y] = graph[y][x] = 1;
}
}
/*获取指定顶点x在vertex中的位置,其中lenNow表示当前长度*/
int getPos(char x, int lenNow)
{
int i = 0;
for (;i < lenNow;i++)
{
if (vertex[i] == x)
{
return i;
}
}
return i;
}
/*打印地图*/
void printgraph()
{
int i, j;
for (i = 0;i < vertices;i++)
{
for (j = 0;j < vertices;j++)
{
printf("%d ", graph[i][j]);
}
printf("\n");
}
}
/*从下标为i的节点进行深度优先遍历*/
void DFS(int i)
{
/*不能越界*/
if (i >=0 && i < vertices)
{
/*输出节点,并置为已访问*/
printf("%c ", vertex[i]);
visited[i] = 1;
int j = 0;
/*对下标为i的这一行进行遍历*/
for (;j < vertices;j++)
{
/*找到未被访问且对应坐标的值为1的列坐标,并对该列进行深度遍历*/
if (visited[j] == 0 && graph[i][j] == 1)
{
DFS(j);
}
}
}
}
/*从下标为i的节点进行广度优先遍历*/
void BFS(int i)
{
if (i >=0 && i < vertices)
{
int queue[vertices], front = 0, rear = 0;
/*将i入队*/
queue[rear] = i;
rear = (rear + 1) % vertices;
while (front != rear)
{
/*出队,并置为已访问*/
int j, pop = queue[front];
front = (front + 1) % vertices;
printf("%c ", vertex[pop]);
visited[pop] = 1;
/*遍历出队下标对应行*/
for (j = 0;j < vertices;j++)
{
/*找到未被访问且对应坐标的值为1的列坐标,并进行入队*/
if (visited[j] == 0 && graph[pop][j] == 1)
{
queue[rear] = j;
rear = (rear + 1) % vertices;
}
}
}
}
}
void travel(int type)
{
initVisited();
int i;
if (type == 0)
{
/*遍历每一个顶点*/
for (i = 0;i < vertices;i++)
{
if (visited[i] == 0)
{
DFS(i);
}
}
}
else
{
for (i = 0;i < vertices;i++)
{
if (visited[i] == 0)
{
BFS(i);
}
}
}
}
void initVisited()
{
int i;
for (i = 0;i < vertices;i++)
{
visited[i] = 0;
}
}
int main()
{
creategraph();
printf("深度优先:");
travel(0);
printf("\n");
printf("广度优先:");
travel(1);
return 0;
}
/*
测试数据
13 12
A K
K L
L M
A H
H I
I J
A E
E F
F G
A B
B C
C D
*/
6 截图
图片来源:百度图片–图的深度优先遍历