图的遍历
调试版
// 基于C语言的图的遍历
#include <stdlib.h>
#include <stdio.h>
#define MAX_EDGE 15
#define MAX_SIZE 9
#define MAX_VERTEX 9
typedef int Edge; // 边
typedef char Vertex; // 顶点
// 定义图的存储结构 -- 邻接矩阵
typedef struct {
int numV, numE;
Edge edge[MAX_EDGE][MAX_EDGE];
Vertex vertex[MAX_VERTEX];
}Graph;
int visited[MAX_VERTEX]; // 访问标记数组 - 未访问:非1, 已访问:1
// 创建图 - 基于邻接矩阵 - 初始化Graph中的变量
void create_graph(Graph *graph)
{
int i, j;
graph->numE = 15;
graph->numV = 9;
/* 读入顶点信息,建立顶点表 */
graph->vertex[0] = 'A';
graph->vertex[1] = 'B';
graph->vertex[2] = 'C';
graph->vertex[3] = 'D';
graph->vertex[4] = 'E';
graph->vertex[5] = 'F';
graph->vertex[6] = 'G';
graph->vertex[7] = 'H';
graph->vertex[8] = 'I';
for (i = 0; i < graph->numV; i++)/* 初始化图 */
{
for (j = 0; j < graph->numV; j++)
{
graph->edge[i][j] = 0;
}
}
graph->edge[0][1] = 1;
graph->edge[0][5] = 1;
graph->edge[1][2] = 1;
graph->edge[1][8] = 1;
graph->edge[1][6] = 1;
graph->edge[2][3] = 1;
graph->edge[2][8] = 1;
graph->edge[3][4] = 1;
graph->edge[3][7] = 1;
graph->edge[3][6] = 1;
graph->edge[3][8] = 1;
graph->edge[4][5] = 1;
graph->edge[4][7] = 1;
graph->edge[5][6] = 1;
graph->edge[6][7] = 1;
for (i = 0; i < graph->numV; i++)
{
for (j = i; j < graph->numV; j++)
{
graph->edge[j][i] = graph->edge[i][j];
}
}
}
// 访问一个vertex顶点
void visit(Graph graph, int index)
{
printf("%c ", graph.vertex[index]);
}
/******************** 深度遍历 ********************/
void dfs(Graph graph, int index)
{
visited[index] = 1;
visit(graph, index);
for (int i = 0; i < graph.numV; i++)
if (graph.edge[index][i] == 1 && !visited)
dfs(graph, i);
}
// 邻接矩阵的DFS
void dfs_traverse(Graph graph)
{
for (int i = 0; i < graph.numV; i++) // 初始化标记数组为未访问
visited[i] = 0;
for (int i = 0; i < graph.numV; i++) // 对图的各个连通分量调用DFS, 如果是连通图,则只会执行一次
if (!visited[i]) // 根据标记数组,判定vertex是否已经被访问
dfs(graph, i);
}
/******************** 广度遍历 ********************/
typedef struct
{
int data[MAX_SIZE];
int front;
int rear;
}Queue; // 循环队列结构
void create_queue(Queue *queue)
{
queue->front = 0;
queue->rear = 0;
}
int isEmpty(Queue queue)
{
if (queue.front == queue.rear) // 队列是否为空
return 1;
return 0;
}
int isFull(Queue queue)
{
if ((queue.rear + 1) % MAX_SIZE == queue.front)
return 1;
return 0;
}
// 入队操作 - 入队的是序列号,而非元素Vertex
void enqueue(Queue *queue, int index)
{
if ((queue->rear + 1) % MAX_SIZE == queue->front) // 队列是否满了
{
printf("The queue is full.");
return;
}
queue->data[queue->rear] = index; // 存储
queue->rear = (queue->rear + 1) % MAX_SIZE; // rear指针后移
}
// 出队
void dequeue(Queue* queue, int* index)
{
if (queue->front == queue->rear) // 队列为空
return;
*index = queue->data[queue->front]; // 将队头元素出队并赋值给index
queue->front = (queue->front + 1) % MAX_SIZE; // front指针后移
}
void print_queue(Graph graph, Queue queue)
{
printf("queue:");
int cursor = queue.front;
while (!isEmpty(queue) && cursor != queue.rear)
{
printf(" %c ", graph.vertex[queue.data[cursor]]);
cursor = (cursor + 1) % MAX_SIZE;
}
printf("
");
}
// 访问某个顶点并入队
void bfs_visit_vertex(Graph graph, int j, Queue* queue)
{
visited[j] = 1;
//visit(graph, j);
printf("入队前:%c ", graph.vertex[j]);
print_queue(graph, *queue);
enqueue(queue, j);
printf("入队后:");
print_queue(graph, *queue);
printf("
");
}
void bfs_traverse(Graph graph)
{
Queue queue;
create_queue(&queue);
for (int i = 0; i < graph.numV; i++)
visited[i] = 0;
for (int i = 0; i < graph.numV; i++) // 对每个连通分量做循环
{
if (!visited[i])
{
printf("
====>%d", i);
bfs_visit_vertex(graph, i, &queue); //访问连通分量的第一个邻接点,并入队
while (!isEmpty(queue))
{
printf("出队前:");
print_queue(graph, queue);
dequeue(&queue, &i); // 将队列中的第一个顶点(序列号)出队
printf("出队后:");
print_queue(graph, queue);
printf("
");
for (int j = 0; j < graph.numV; j++) // 遍历出队的顶点的所有的邻接点,然后将邻接点全部入队
{
if (graph.edge[i][j] == 1 && !visited[j]) // 未访问过的邻接点
{
bfs_visit_vertex(graph, j, &queue);
}
}
}
}
}
}
int main()
{
Graph graph;
create_graph(&graph);
printf("
深度遍历:");
dfs_traverse(graph);
printf("
广度遍历:");
bfs_traverse(graph);
return 0;
}
最终版
// 基于C语言的图的遍历
#include <stdlib.h>
#include <stdio.h>
#define MAX_EDGE 15
#define MAX_SIZE 9
#define MAX_VERTEX 9
typedef int Edge; // 边
typedef char Vertex; // 顶点
// 定义图的存储结构 -- 邻接矩阵
typedef struct {
int numV, numE;
Edge edge[MAX_EDGE][MAX_EDGE];
Vertex vertex[MAX_VERTEX];
}Graph;
int visited[MAX_VERTEX]; // 访问标记数组 - 未访问:非1, 已访问:1
// 创建图 - 基于邻接矩阵 - 初始化Graph中的变量
void create_graph(Graph *graph)
{
int i, j;
graph->numE = 15;
graph->numV = 9;
/* 读入顶点信息,建立顶点表 */
graph->vertex[0] = 'A';
graph->vertex[1] = 'B';
graph->vertex[2] = 'C';
graph->vertex[3] = 'D';
graph->vertex[4] = 'E';
graph->vertex[5] = 'F';
graph->vertex[6] = 'G';
graph->vertex[7] = 'H';
graph->vertex[8] = 'I';
for (i = 0; i < graph->numV; i++)/* 初始化图 */
{
for (j = 0; j < graph->numV; j++)
{
graph->edge[i][j] = 0;
}
}
graph->edge[0][1] = 1;
graph->edge[0][5] = 1;
graph->edge[1][2] = 1;
graph->edge[1][8] = 1;
graph->edge[1][6] = 1;
graph->edge[2][3] = 1;
graph->edge[2][8] = 1;
graph->edge[3][4] = 1;
graph->edge[3][7] = 1;
graph->edge[3][6] = 1;
graph->edge[3][8] = 1;
graph->edge[4][5] = 1;
graph->edge[4][7] = 1;
graph->edge[5][6] = 1;
graph->edge[6][7] = 1;
for (i = 0; i < graph->numV; i++)
{
for (j = i; j < graph->numV; j++)
{
graph->edge[j][i] = graph->edge[i][j];
}
}
}
// 访问一个vertex顶点
void visit(Graph graph, int index)
{
printf("%c ", graph.vertex[index]);
}
/******************** 深度遍历 ********************/
void dfs(Graph graph, int index)
{
visited[index] = 1;
visit(graph, index);
for (int i = 0; i < graph.numV; i++)
if (graph.edge[index][i] == 1 && !visited)
dfs(graph, i);
}
// 邻接矩阵的DFS
void dfs_traverse(Graph graph)
{
for (int i = 0; i < graph.numV; i++) // 初始化标记数组为未访问
visited[i] = 0;
for (int i = 0; i < graph.numV; i++) // 对图的各个连通分量调用DFS, 如果是连通图,则只会执行一次
if (!visited[i]) // 根据标记数组,判定vertex是否已经被访问
dfs(graph, i);
}
/******************** 广度遍历 ********************/
typedef struct
{
int data[MAX_SIZE];
int front;
int rear;
}Queue; // 循环队列结构
void create_queue(Queue *queue)
{
queue->front = 0;
queue->rear = 0;
}
int isEmpty(Queue queue)
{
if (queue.front == queue.rear) // 队列是否为空
return 1;
return 0;
}
int isFull(Queue queue)
{
if ((queue.rear + 1) % MAX_SIZE == queue.front)
return 1;
return 0;
}
// 入队操作 - 入队的是序列号,而非元素Vertex
void enqueue(Queue *queue, int index)
{
if ((queue->rear + 1) % MAX_SIZE == queue->front) // 队列是否满了
{
printf("The queue is full.");
return;
}
queue->data[queue->rear] = index; // 存储
queue->rear = (queue->rear + 1) % MAX_SIZE; // rear指针后移
}
// 出队
void dequeue(Queue* queue, int* index)
{
if (queue->front == queue->rear) // 队列为空
return;
*index = queue->data[queue->front]; // 将队头元素出队并赋值给index
queue->front = (queue->front + 1) % MAX_SIZE; // front指针后移
}
void bfs_traverse(Graph graph)
{
Queue queue;
create_queue(&queue);
for (int i = 0; i < graph.numV; i++)
visited[i] = 0;
for (int i = 0; i < graph.numV; i++) // 对每个顶点做循环
{
if (!visited[i])
{
/*printf("
====>%d", i);*/
visited[i] = 1;
visit(graph, i);
enqueue(&queue, i);
while (!isEmpty(queue))
{
dequeue(&queue, &i);
for (int j = 0; j < graph.numV; j++)
{
if (graph.edge[i][j] == 1 && !visited[j])
{
visited[j] = 1;
visit(graph, j);
enqueue(&queue, j);
}
}
}
}
}
}
int main()
{
Graph graph;
create_graph(&graph);
printf("
深度遍历:");
dfs_traverse(graph);
printf("
广度遍历:");
bfs_traverse(graph);
return 0;
}