【PTA数据结构 | C语言版】列出连通集

本专栏持续输出数据结构题目集,欢迎订阅。

文章目录

题目

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

输入格式:

输入第 1 行给出 2 个整数 n (0<n≤10) 和 m,分别是图的顶点数和边数。随后 m 行,每行给出一条边的两个端点。每行中的数字之间用 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 }

代码

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_VERTEX 10

typedef struct Node {
    int vertex;
    struct Node* next;
} Node;

typedef struct {
    Node* adj[MAX_VERTEX];
    int n;
} Graph;

typedef struct {
    int data[MAX_VERTEX];
    int top;
} Stack;

typedef struct {
    int data[MAX_VERTEX];
    int front, rear;
} Queue;

// 函数声明
void initGraph(Graph* g, int n);
void addEdge(Graph* g, int src, int dest);
void DFS(Graph* g, int v, int visited[], int component[], int* count);
void BFS(Graph* g, int v, int visited[], int component[], int* count);
void initQueue(Queue* q);
int isQueueEmpty(Queue* q);
void enqueue(Queue* q, int v);
int dequeue(Queue* q);
void initStack(Stack* s);
int isStackEmpty(Stack* s);
void push(Stack* s, int v);
int pop(Stack* s);
int peek(Stack* s);

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    
    Graph g;
    initGraph(&g, n);
    
    for (int i = 0; i < m; i++) {
        int src, dest;
        scanf("%d %d", &src, &dest);
        addEdge(&g, src, dest);
    }
    
    // DFS遍历
    int visited[MAX_VERTEX] = {0};
    for (int i = 0; i < n; i++) {
        if (!visited[i]) {
            int component[MAX_VERTEX];
            int count = 0;
            DFS(&g, i, visited, component, &count);
            
            printf("{");
            for (int j = 0; j < count; j++) {
                printf(" %d", component[j]);
            }
            printf(" }\n");
        }
    }
    
    // BFS遍历
    memset(visited, 0, sizeof(visited));
    for (int i = 0; i < n; i++) {
        if (!visited[i]) {
            int component[MAX_VERTEX];
            int count = 0;
            BFS(&g, i, visited, component, &count);
            
            printf("{");
            for (int j = 0; j < count; j++) {
                printf(" %d", component[j]);
            }
            printf(" }\n");
        }
    }
    
    return 0;
}

// 初始化图
void initGraph(Graph* g, int n) {
    g->n = n;
    for (int i = 0; i < n; i++) {
        g->adj[i] = NULL;
    }
}

// 添加无向边(按编号递增顺序插入)
void addEdge(Graph* g, int src, int dest) {
    // 添加src->dest的边(按递增顺序插入)
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->vertex = dest;
    
    Node* prev = NULL;
    Node* curr = g->adj[src];
    while (curr != NULL && curr->vertex < dest) {
        prev = curr;
        curr = curr->next;
    }
    
    if (prev == NULL) {
        newNode->next = g->adj[src];
        g->adj[src] = newNode;
    } else {
        newNode->next = curr;
        prev->next = newNode;
    }
    
    // 添加dest->src的边(按递增顺序插入)
    newNode = (Node*)malloc(sizeof(Node));
    newNode->vertex = src;
    
    prev = NULL;
    curr = g->adj[dest];
    while (curr != NULL && curr->vertex < src) {
        prev = curr;
        curr = curr->next;
    }
    
    if (prev == NULL) {
        newNode->next = g->adj[dest];
        g->adj[dest] = newNode;
    } else {
        newNode->next = curr;
        prev->next = newNode;
    }
}

// 初始化栈
void initStack(Stack* s) {
    s->top = -1;
}

// 判断栈是否为空
int isStackEmpty(Stack* s) {
    return s->top == -1;
}

// 入栈
void push(Stack* s, int v) {
    s->data[++(s->top)] = v;
}

// 出栈
int pop(Stack* s) {
    return s->data[(s->top)--];
}

// 获取栈顶元素
int peek(Stack* s) {
    return s->data[s->top];
}

// 非递归深度优先搜索(避免栈溢出)
void DFS(Graph* g, int v, int visited[], int component[], int* count) {
    Stack stack;
    initStack(&stack);
    
    push(&stack, v);
    
    while (!isStackEmpty(&stack)) {
        int u = pop(&stack);
        
        if (!visited[u]) {
            visited[u] = 1;
            component[(*count)++] = u;
            
            // 逆序处理邻接点,确保按编号升序访问
            Node* temp = g->adj[u];
            Node* nodes[MAX_VERTEX];
            int nodeCount = 0;
            
            while (temp != NULL) {
                nodes[nodeCount++] = temp;
                temp = temp->next;
            }
            
            for (int i = nodeCount - 1; i >= 0; i--) {
                int adjVertex = nodes[i]->vertex;
                if (!visited[adjVertex]) {
                    push(&stack, adjVertex);
                }
            }
        }
    }
}

// 初始化队列
void initQueue(Queue* q) {
    q->front = q->rear = 0;
}

// 判断队列是否为空
int isQueueEmpty(Queue* q) {
    return q->front == q->rear;
}

// 入队
void enqueue(Queue* q, int v) {
    q->data[q->rear++] = v;
}

// 出队
int dequeue(Queue* q) {
    return q->data[q->front++];
}

// 广度优先搜索
void BFS(Graph* g, int v, int visited[], int component[], int* count) {
    Queue q;
    initQueue(&q);
    
    visited[v] = 1;
    enqueue(&q, v);
    component[(*count)++] = v;
    
    while (!isQueueEmpty(&q)) {
        int u = dequeue(&q);
        
        Node* temp = g->adj[u];
        while (temp != NULL) {
            int adjVertex = temp->vertex;
            if (!visited[adjVertex]) {
                visited[adjVertex] = 1;
                enqueue(&q, adjVertex);
                component[(*count)++] = adjVertex;
            }
            temp = temp->next;
        }
    }
}
相关推荐
渡我白衣11 分钟前
C++:链接的两难 —— ODR中的强与弱符号机制
开发语言·c++·人工智能·深度学习·网络协议·算法·机器学习
小龙报18 分钟前
《算法通关指南:数据结构和算法篇 --- 顺序表相关算法题》--- 1.移动零,2.颜色分类
c语言·开发语言·数据结构·c++·算法·学习方法·visual studio
奔跑吧邓邓子21 分钟前
【C语言实战(67)】从0到1:C语言多线程编程实战(POSIX线程版)
c语言·多线程编程·开发实战·posix
再睡一夏就好30 分钟前
【C++闯关笔记】使用红黑树简单模拟实现map与set
java·c语言·数据结构·c++·笔记·语法·1024程序员节
im_AMBER35 分钟前
Leetcode 43
笔记·学习·算法·leetcode
ceffans1 小时前
PDF文档中表格以及形状解析-后续处理(线段生成最小多边形)
c++·windows·算法·pdf
mifengxing1 小时前
力扣每日一题——接雨水
c语言·数据结构·算法·leetcode·动态规划·
魔云连洲2 小时前
前端树形结构过滤算法
前端·算法
小龙报2 小时前
《算法通关指南:数据结构和算法篇 --- 顺序表相关算法题》--- 询问学号,寄包柜,合并两个有序数组
c语言·开发语言·数据结构·c++·算法·学习方法·visual studio
序属秋秋秋2 小时前
《Linux系统编程之开发工具》【编译器 + 自动化构建器】
linux·运维·服务器·c语言·c++·自动化·编译器