列出图的连通集

  • 题目来源:

浙江大学在慕课网上开设的《数据结构》课,陈越老师、何钦铭老师主讲,课后作业的一道题。

  • 题目描述:

  • 思路:

非常基础的一道题,主要考察图的DFS遍历和BFS遍历,最后注意输出的格式就可以了。

  • C语言实现:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MaxVerterNum 100  //最大定点数设为100
#define INFINITY 65535  //无穷设为双字节无符号整数的最大值65535

typedef int WeightType;  //边的权值设为int类型
typedef char DataType;  //顶点存储的数据类型设置为字符类型
typedef int Vertex;  //用顶点下标表示顶点,为整型

bool Visited[MaxVerterNum];

struct QNode
{
    int* Data;  //存储元素的数组
    int Front;  //队列的头指针
    int Rear;  //队列的尾指针
    int MaxSize;  //队列的最大容量
};

//创建一个队列
struct QNode* CreateQueue(int MaxSize)
{
    struct QNode* Q = (struct QNode*)malloc(sizeof(struct QNode));
    Q->Data = (int *)malloc(MaxSize * sizeof(int));
    Q->Front = Q->Rear = 0;
    Q->MaxSize = MaxSize;
    return Q;
}

bool IsFull(struct QNode* Q)
{
    return ((Q->Rear + 1) % Q->MaxSize) == Q->Front;
}

//在队列尾插入一个元素
//参数 struct QNode* Q 要操作的队列
//     int x  待插入的元素
bool AddQ(struct QNode* Q, int x)
{
    if (IsFull(Q))  //判断队列是否为空
    {
        printf("队列满,不能再插入元素\n");
        return false;
    }
    else
    {
        Q->Rear = (Q->Rear + 1) % Q->MaxSize;
        Q->Data[Q->Rear] = x;
        return true;
    }
}

//判断队列是否为空
bool IsEmpty(struct QNode* Q)
{
    return (Q->Front == Q->Rear);
}
//在队列头部删除一个元素
int DeleteQ(struct QNode* Q)
{
    if (IsEmpty(Q))
    {
        printf("队列为空\n");
        return false;
    }
    else
    {
        Q->Front = (Q->Front + 1) % Q->MaxSize;
        return Q->Data[Q->Front];
    }

}

struct GNode 
{
    int Nv;  //顶点数
    int Ne;  //边数
    WeightType G[MaxVerterNum][MaxVerterNum];  //邻接矩阵
    DataType Data[MaxVerterNum][MaxVerterNum];  //存顶点的数据
    /*如果顶点无数据,此时Data[]可以不出现*/
};
//描述边的类型
struct ENode
{
    Vertex V1, V2;  //有向边<V1,V2>
    WeightType Weight;  //权重
};
//作用:初始化一个有VertexNum个顶点但没有边的图
struct GNode* CreateGraph(int VertexNum)
{
    Vertex V, W;
    struct GNode* Graph;
    Graph = (struct GNode*)malloc(sizeof(struct GNode));  //建立图
    Graph->Nv = VertexNum;
    Graph->Ne = 0;

    //初始化邻接矩阵
    for (V = 0;V < Graph->Nv;V++)
    {
        for (W = 0;W < Graph->Nv;W++)
        {
            Graph->G[V][W] = INFINITY;
        }
    }
    return Graph;
}

//作用:在图中插入边
void InsertEdge(struct GNode* Graph,struct ENode* E)
{
    ////插入边<V1,V2>
    //Graph->G[E->V1][E->V2] = E->Weight;
    ////若是无向图,还需要插入<V2,V1>
    //Graph->G[E->V2][E->V1] = E->Weight;

    //插入边<V1,V2>
    Graph->G[E->V1][E->V2] = 1;
    //若是无向图,还需要插入<V2,V1>
    Graph->G[E->V2][E->V1] = 1;
}
//作用:构建一个图,供主函数调用
struct GNode* BulidGraph()
{
    Vertex V;
    int NV;
    struct ENode* E;
    struct GNode* Graph;
    scanf("%d",&NV);  //读入顶点个数
    Graph = CreateGraph(NV);
    scanf("%d",&(Graph->Ne));  //读入边数

    if (Graph->Ne != 0)
    {
        E = (struct ENode*)malloc(sizeof(struct ENode));
        for (int i = 0;i < Graph->Ne;i++)
        {
            ////如果权重不是整型,Weight的读入格式要改
            //scanf("%d %d %d",&E->V1,&E->V2,&E->Weight);
            scanf("%d %d", &E->V1, &E->V2);
            InsertEdge(Graph,E);
        }
    }

    ////如果顶点有数据的话,读入数据
    //for (V = 0;V < Graph->Nv;V++)
    //{
    //  scanf("%c",&(Graph->Data[V]));
    //}

    return Graph;
}

void Visit(Vertex V)
{
    printf(" %d",V);
}
//这个DFS是我自己写的
//void DFS(struct GNode* Graph,Vertex V,void(* Visit)(Vertex))
//{
//  Vertex W;
//  Visit(V);
//  Visited[V] = true;
//
//  for (W = V + 1; W < Graph->Nv; W++)
//  {
//      if (Graph->G[V][W] == 1)
//      {
//          if (!Visited[W])
//          {
//              DFS(Graph, W, Visit);
//          }
//      }
//  }
//}

void DFS(struct GNode* Graph, Vertex V, void(*Visit)(Vertex))
{
    Vertex j;
    Visited[V] = true;
    Visit(V);

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

void DFSTraverser(struct GNode* Graph)
{
    int i = 0;
    //初始化所有顶点都是未访问的状态
    for (i = 0;i < Graph->Nv;i++)
    {
        Visited[i] = false;
    }

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

bool IsEdge(struct GNode* Graph,Vertex V,Vertex W)
{
    return Graph->G[V][W] < INFINITY ? true : false;
}

void BFS(struct GNode* Graph, Vertex S, void(*Visit)(Vertex))
{
    struct QNode* Q;
    Vertex V, W;
    Q = CreateQueue(20);

    Visited[S] = true;
    Visit(S);
    AddQ(Q,S);

    while (!IsEmpty(Q))
    {
        V = DeleteQ(Q);
        for (W = 0;W < Graph->Nv;W++)
        {
            //若W是V的邻接点 并且 没有访问过
            if (!Visited[W] && IsEdge(Graph,V,W))
            {
                Visit(W);  //访问节点
                Visited[W] = true;
                AddQ(Q,W);
            }
        }
    }
}
void BFSTraverser(struct GNode* Graph)
{
    int i = 0;
    //初始化所有顶点都是未访问的状态
    for (i = 0; i < Graph->Nv; i++)
    {
        Visited[i] = false;
    }

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

int main()
{
    struct GNode* Graph = BulidGraph();
    // printf("图建立完毕.\n");
    DFSTraverser(Graph);
    BFSTraverser(Graph);
    // system("pause");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Manual-Linux/p/11367543.html