C语言邻接表法的实现

一、邻接表示意图

        邻接表相比于邻接矩阵来说,大大减少了存储空间的浪费情况。如图1-1为邻接表示意图,其中V0~V3表示的是图的顶点(vertex),后面跟随的则是邻接节点。邻接节点的数字表示顶点下一个连接的顶点的索引,如V1邻接节点的数字为2和0,则表示V1节点连接了V2和V0节点,如图1-2.

图1-1

 图1-2

二、代码实现

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define MAX_VERTEX_NUM 10

char name[5] = {'a', 'b', 'c', 'd', 'e'};

typedef struct adjNode
{
    int index;
    struct adjNode *next;
} adjNode, *padjNode;

typedef struct verNode
{
    char verName;
    adjNode *first;
} verNode, verMat[MAX_VERTEX_NUM];

typedef struct graph
{
    int verNum, adjNum;
    verMat vm;
} graph, *pgraph;

void initGraph(pgraph *g)
{
    (*g) = (pgraph)malloc(sizeof(graph));
    (*g)->verNum = (*g)->adjNum = 0;
    for (int i = 0; i < MAX_VERTEX_NUM; i++)
    {
        (*g)->vm[i].verName = '#';
    }
}

void insertVertex(pgraph *g, char name)
{
    for (int i = 0; (*g)->verNum != MAX_VERTEX_NUM; i++)
    {
        if ((*g)->vm[i].verName == '#')
        {
            (*g)->vm[i].verName = name;
            (*g)->vm[i].first = NULL;
            break;
        }
    }
    (*g)->verNum++;
}

void showAllVerName(pgraph *g)
{
    int index = 0;
    printf("图的顶点信息:");
    while (index != (*g)->verNum)
    {
        printf("%c ", (*g)->vm[index].verName);
        index++;
    }
}

/*
构建图:
    a  → b
    ↓ ↗ ↓
    c  ← d ← e

    source,direction∈(1~MAX_VERTEX_NUM)
*/
void pointTo(pgraph *g, int source, int direction)
{
    padjNode node = (padjNode)malloc(sizeof(adjNode));
    node->index = direction;
    node->next = NULL;

    // 当顶点无任何边
    if ((*g)->vm[source - 1].first == NULL)
    {
        (*g)->vm[source - 1].first = node;
        printf("%c->%c成功!\n", (*g)->vm[source - 1].verName, (*g)->vm[direction - 1].verName);
        (*g)->adjNum++;
        return;
    }
    // 当顶点有一条或一条以上的边
    else
    {
        padjNode q = (*g)->vm[source - 1].first;
        // 当顶点链接的第一条边对应的顶点已存在
        if (q->index == direction)
        {
            printf("已存在%c->%c的边\n", (*g)->vm[source - 1].verName, (*g)->vm[direction - 1].verName);
            return;
        }

        // 移动到最后一条边
        while (q->next != NULL)
        {
            q = q->next;
            // 当顶点链接的边对应的顶点已存在
            if (q->index == direction)
            {
                printf("已存在%c->%c的边\n", (*g)->vm[source - 1].verName, (*g)->vm[direction - 1].verName);
                return;
            }
        }

        // 在最后插入邻接节点
        q->next = node;
        printf("%c->%c成功!\n", (*g)->vm[source - 1].verName, (*g)->vm[direction - 1].verName);
        (*g)->adjNum++;
        return;
    }
}

void showAllAdjnodeOfNode(pgraph *g)
{
    padjNode q;
    for (int i = 0; i < (*g)->verNum; i++)
    {
        printf("%c", (*g)->vm[i].verName);
        q = (*g)->vm[i].first;
        for (int j = 0; q != NULL; j++)
        {
            printf("->%c",(*g)->vm[q->index-1].verName);
            q = q->next;
        }
        printf("\n");
    }
}

int main(int argc, char const *argv[])
{
    pgraph g;
    initGraph(&g);
    for (int i = 0; i < 5; i++)
    {
        insertVertex(&g, name[i]);
    }
    
    pointTo(&g, 1, 2);
    pointTo(&g, 1, 3);
    pointTo(&g, 2, 4);
    pointTo(&g, 4, 3);
    pointTo(&g, 3, 2);
    pointTo(&g, 5, 4);

    showAllAdjnodeOfNode(&g);
    showAllVerName(&g);

    return 0;
}

         

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值