邻接表 计算连通分量C语言 数据结构

邻接表存储的图计算连通分量

按照王道书的函数名称做滴

#include<stdio.h>
#include<string.h>
#include <iostream>
#include<algorithm>

using namespace std;
#define MVNum 2
#define INF 0x3f3f3f3f
int vis[MVNum];

typedef struct ArcNode /* 边表结点  */
{
    int adjvex;    /* 邻接点域,存储该顶点对应的下标 */
    int info;         /* 用于存储权值,对于非网图可以不需要 */
    struct ArcNode* nextarc; /* 链域,指向下一个邻接点 */
}ArcNode;

typedef struct VNode /* 顶点表结点 */
{
    char data; /* 顶点域,存储顶点信息 */
    ArcNode* firstarc; /* 边表头指针 */
}VNode, AdjList[MVNum];//头结点数组
typedef struct
{
    AdjList vertices;
    int vexnum, arcnum; /* 图中当前顶点数和边数 */
}ALGraph;
int LocateVex(ALGraph& G, char v)//找到v在邻接表G中的位置
{
    for (int i = 0; i < G.vexnum; i++)
    {
        if (G.vertices[i].data == v)
            return i;
    }
    return -1;
}

void ListGraphInit(ALGraph& L, int map[MVNum][MVNum]) {
    memset(&L, 0, sizeof(L));
    for (int i = 0; i < MVNum; i++) {
        L.vexnum++;
        int mark = 0;
        
        for (int j = 0; j < MVNum; j++) {

            if(mark==0 && j==MVNum-1 && map[i][j]==INF) { //如果一个点没有任何边 则创建新的无边头结点
                L.vertices[i].firstarc = (ArcNode*)malloc(sizeof(ArcNode));
                L.vertices[i].firstarc->adjvex = -1;
                L.vertices[i].firstarc->info = 0;
                L.vertices[i].firstarc->nextarc = nullptr;
            }

            if (map[i][j] != INF && (i != j)) {
                L.arcnum++;
                if (!mark) { //建立头结点 
                    mark++;
                    L.vertices[i].firstarc = (ArcNode*)malloc(sizeof(ArcNode));
                    L.vertices[i].firstarc->adjvex = j;
                    L.vertices[i].firstarc->info = 0;
                    L.vertices[i].firstarc->nextarc = nullptr;
                }
                else
                {
                    //建立该顶点与其他顶点的边
                    ArcNode* p = L.vertices[i].firstarc, * q;
                    while (p->nextarc != nullptr)
                        p = p->nextarc;
                    q = (ArcNode*)malloc(sizeof(ArcNode));
                    p->nextarc = q;
                    q->info = map[i][j];
                    q->adjvex = j;
                    q->nextarc = nullptr;
                }


                }
            }
            
        }
    }


int NextNeighbor(ALGraph G, int x, int y)
{
    //以邻接表作为存储结构
    if (x != -1)
    {
        ArcNode* p = G.vertices[x].firstarc;
        while (p != NULL && p->adjvex != y)
        {
            p = p->nextarc;
        }
        if (p != NULL && p->nextarc != NULL)
            return p->nextarc->adjvex;  //返回除了y以外x的下一个邻接点 若y是x最后一个邻接点 返回-1
    }
    return -1;
}

int FirstNeighbor(ALGraph G, int x) {//求G的顶点x的第一个邻接点 有就返回顶点号 没有邻接点就返回-1
    
    ArcNode* p = G.vertices[x].firstarc;
    if (p->adjvex) return p->adjvex;
    return -1;
}
void DFS(ALGraph G, int v)
{
    int w;
    vis[v] = 1; //结点标记
    for(w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w))
    {
        if (!vis[w])
            DFS(G, w);
    }
}


void ListGraphOutput(ALGraph& L) {
    printf("邻接表信息如下: \n");
    printf("\t该邻接表共有%d个结点与%d条边\n",L.vexnum,L.arcnum );
    printf("\t结点信息如下: \n");

    printf("\t弧的具体信息如下: \n");
    for (int i = 0; i < L.vexnum; i++) {
        printf("\t\t%d->", i);
        if (L.vertices[i].firstarc->adjvex<0) return;
        printf("%d", L.vertices[i].firstarc->adjvex);
        ArcNode* p = L.vertices[i].firstarc->nextarc;
        while (p) {
            printf("->%d", p->adjvex);
            p = p->nextarc;
        }
        putchar(10);
    }
    putchar(10);
}


int main(void)
{
    ALGraph G;
    int m = INF;
    

    int map[MVNum][MVNum] = {
        0, 5,
        2, 0,
    };
    ListGraphInit(G, map);
    ListGraphOutput(G);
    int num = 0;
    memset(vis, 0, sizeof(vis));  //大小裁剪
    

    for (int v = 0; v < G.vexnum; v++) // 读入顶点信息,建立顶点表
    {
        if (!vis[v])
        {
            DFS(G, v);
            num++;
        }
    }
    printf("\n连通分量个数:%d\n", num);
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值