06-图1 列出连通集 (25分)

题目描述

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:

输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照"{v1 v2 ... vk}"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

解题思路

首先选择用什么方式表示图,邻接矩阵还是邻接表。根据题意:按编号递增的顺序访问邻接点,如果用邻接表的话插入的时候就很麻烦,因为需要额外的判断来保证递增顺序,所以我选择了用邻接矩阵表示图。那么可以先根据输入构建邻接矩阵,然后再对矩阵DFS和BFS。对于DFS,每遇到一个未访问邻接点就递归;对于BFS,和二叉树的层次遍历类似,借助于队列实现,每遇到一个未访问邻接点就入队。

代码

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 10

struct Graph {
    int vertexCount;    //顶点数
    int edgeCount;      //边数
    int matrix[MAXSIZE][MAXSIZE];   //用邻接矩阵表示图
};
typedef struct Graph *MGraph;

//用链表表示队列
struct QNode {
    int data;
    struct QNode *next;
};
typedef struct QNode *Queue;

int visited[MAXSIZE] = {0};     //判断结点是否访问过

MGraph createGraph(int N, int M);
void listConnectedSet_DFS(MGraph graph);
void listConnectedSet_BFS(MGraph graph);
void DFS(MGraph graph, int index);
void BFS(MGraph graph, int index);
Queue createQueue();
void pushQueue(Queue queue, int index);
int popQueue(Queue queue);
int isEmpty(Queue queue);

int main() {
    int N, M;
    scanf("%d %d", &N, &M);
    MGraph graph = createGraph(N, M);
    listConnectedSet_DFS(graph);
    for (int i = 0; i < N; i++) {   //重置访问数组
        visited[i] = 0;
    }
    listConnectedSet_BFS(graph);
    return 0;
}

//创建无向图
MGraph createGraph(int N, int M) {
    MGraph graph = (MGraph) malloc(sizeof(struct Graph));
    graph->vertexCount = N;
    graph->edgeCount = M;
    for (int i = 0; i < MAXSIZE; i++) {
        for (int j = 0; j < MAXSIZE; j++) {
            graph->matrix[i][j] = 0;
        }
    }
    for (int i = 0; i < M; i++) {
        int v1, v2;
        scanf("%d %d", &v1, &v2);
        graph->matrix[v1][v2] = 1;
        graph->matrix[v2][v1] = 1;
    }
    return graph;
}

//对整个图DFS
void listConnectedSet_DFS(MGraph graph) {
    for (int i = 0; i < graph->vertexCount; i++) {
        if (!visited[i]) {
            printf("{");
            DFS(graph, i);
            printf(" }\n");
        }
    }
}

//对整个图BFS
void listConnectedSet_BFS(MGraph graph) {
    for (int i = 0; i < graph->vertexCount; i++) {
        if (!visited[i]) {
            printf("{");
            BFS(graph, i);
            printf(" }\n");
        }
    }
}

//对一个连通集DFS
void DFS(MGraph graph, int index) {
    visited[index] = 1;
    printf(" %d", index);
    for (int i = 0; i < graph->vertexCount; i++) {
        if (graph->matrix[index][i] == 1 && !visited[i]) {
            DFS(graph, i);
        }
    }
}

//对一个连通集BFS
void BFS(MGraph graph, int index) {
    Queue queue = createQueue();
    pushQueue(queue, index);
    visited[index] = 1;
    printf(" %d", index);
    while (!isEmpty(queue)) {
        int index = popQueue(queue);
        for (int i = 0; i < graph->vertexCount; i++) {
            if (graph->matrix[index][i] == 1 && !visited[i]) {
                pushQueue(queue, i);
                printf(" %d", i);
                visited[i] = 1;
            }
        }
    }
}

//新建队列,返回哨兵结点
Queue createQueue() {
    Queue queue = (Queue) malloc(sizeof(struct QNode));
    queue->data = -1; queue->next = NULL;
    return queue;
}

//尾插法入队
void pushQueue(Queue queue, int index) {
    Queue rear = queue;
    while (rear->next) rear = rear->next;
    Queue node = (Queue) malloc(sizeof(struct QNode));
    node->data = index; node->next = NULL;
    rear->next = node;
}

//删除首结点
int popQueue(Queue queue) {
    if (!queue->next) return -1;
    Queue target = queue->next;
    int ret = target->data;
    queue->next = target->next;
    free(target);
    return ret;
}

//判断队列是否为空
int isEmpty(Queue queue) {
    return queue->next == NULL;
}
posted @ 2020-03-27 11:43  AndyHY  阅读(256)  评论(0编辑  收藏  举报