数据结构PTA 基础实验6-2.1 列出连通集

基础实验6-2.1 列出连通集

题目

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

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

输出格式:
按照"{ v1 v​2 … v​k​​ }"的格式,每行输出一个连通集。先输出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 }

解法

思路
这就是一道深度优先遍历和广度优先遍历的题目。

  1. 因为此图的顶点较少,可以使用邻接矩阵存储,并且不必要用动态矩阵。
  2. 在进行深度优先遍历时,只需要用好Visited数组即可,保证下次迭代访问的顶点不仅是此时的邻接点,还要求没有被访问。
  3. 在进行广度优先遍历时,需要涉及到队列的操作:创建一个空队、顶点入队、顶点出队、判断队是否为空。在这里为了简便起见,用数组作为队的构成方式,当然也可以用链表。
    广度优先遍历需要刚开始的时候就入队一个顶点,然后进入while循环,只要队不空,这个循环一直做。循环内就是弹出队列的一个顶点,然后按照大小顺序,遍历此点的所有邻接点,并把这些点入队。

实现

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

#define MAXN 10
#define INFINITY 100000
#define MAXSIZE 10+1

typedef int WeightType;
typedef int Vertex;

typedef struct QNode *Queue;
struct QNode
{
    int Start;
    int End;
    Vertex Arr[MAXSIZE];
};


typedef struct GNode *PtrToGNode;
typedef PtrToGNode MGraph;
struct GNode
{
    int Nv;
    int Ne;
    WeightType G[MAXN][MAXN];
};

typedef struct ENode *PtrToENode;
typedef PtrToENode Edge;
struct ENode
{
    Vertex V1, V2;
    WeightType W;
};

MGraph CreateGraph(int VertexNum)
{
    Vertex i,j;
    MGraph Graph = (MGraph)malloc(sizeof(struct GNode));
    Graph->Nv = VertexNum;
    Graph->Ne = 0;
    for(i=0; i<Graph->Nv; i++)
        for(j=0; j<Graph->Nv; j++)
            Graph->G[i][j] = INFINITY;

    return Graph;
}

void InsertEdge(MGraph Graph, Edge E)
{
    Graph->G[E->V1][E->V2] = E->W;
    Graph->G[E->V2][E->V1] = E->W;
}

MGraph BuildGraph(int VertexNum, int EdgeNum)
{
    MGraph Graph = CreateGraph(VertexNum);
    Graph->Ne = EdgeNum;

    int i;
    Edge E = (Edge)malloc(sizeof(struct ENode));
    for(i=0; i<Graph->Ne; i++)
    {
        scanf("%d %d", &E->V1, &E->V2);
        E->W = 1;
        InsertEdge(Graph, E);
    }

    return Graph;
}

void Visit(Vertex i)
{
    printf("%d ", i);
}

int Visited[MAXN] = {0};
void DFS(MGraph Graph, Vertex V, void (*Visit)(Vertex))
{
    Visit(V);
    Visited[V] = 1;

    Vertex W;
    for(W=0; W<Graph->Nv; W++)
    {
        if(!Visited[W] && Graph->G[V][W] != INFINITY)
            DFS(Graph, W, Visit);
    }

}

Queue CreateQueue()
{
    Queue Q = (Queue)malloc(sizeof(struct QNode));
    Q->Start = 0;
    Q->End = 0;
    return Q;
}

void AddQ(Queue Q, Vertex V)
{
    Q->Arr[Q->End++] = V;
    if(Q->End >= MAXSIZE)
        Q->End = Q->End % MAXSIZE;
}

Vertex DeleteQ(Queue Q)
{
    Vertex tmp = Q->Arr[Q->Start++];
    if(Q->Start >= MAXSIZE)
        Q->Start = Q->Start % MAXSIZE;
    return tmp;
}

int IsEmptyQ(Queue Q)
{
    if(Q->Start == Q->End)
        return 1;
    else
        return 0;
}

void BFS(MGraph Graph, Vertex V, void (*Visit)(Vertex))
{
    Visit(V);
    Visited[V] = 1;

    Queue Q = CreateQueue();
    AddQ(Q, V);

    Vertex tmpV,i;
    while(!IsEmptyQ(Q))
    {
        tmpV = DeleteQ(Q);
        for(i=0; i<Graph->Nv; i++)
        {
            if( Graph->G[tmpV][i] != INFINITY && !Visited[i] )
            {
                Visit(i);
                Visited[i] = 1;
                AddQ(Q, i);
            }
        }
    }


}

int main()
{
    int N,M;
    scanf("%d %d", &N, &M);
    MGraph Graph = BuildGraph(N, M);

    Vertex StartPoint = 0;
    while(StartPoint < Graph->Nv)
    {
        if(Visited[StartPoint] == 0)
        {
            printf("{ ");
            DFS(Graph, StartPoint, Visit);
            printf("}\n");
        }
        StartPoint++;
    }

    //clear the Visited[]
    for(StartPoint = 0; StartPoint<Graph->Nv; StartPoint++)
        Visited[StartPoint] = 0;

    StartPoint = 0;
    while(StartPoint < Graph->Nv)
    {
        if(Visited[StartPoint] == 0)
        {
            printf("{ ");
            BFS(Graph, StartPoint, Visit);
            printf("}\n");
        }
        StartPoint++;
    }


    return 0;
}

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值