【二十六】图的存储结构--邻接链表法

1、邻接链表法
基本思想:

这里写图片描述

示例:
这里写图片描述

2、数据结点定义

这里写图片描述

3、算法实现

数据类型声明

/*
* 邻接链表法,数据结构定义
*/
typedef struct _struct_lgraph
{
    int count;          //存储结点数目
    LVertex **data;     //一个指针数组,记录与顶点相关的数据描述
    Linklist **la;      //一个指针数组,记录每个结点的链表地址
}TLGraph;

/*
* 链表数据结点定义
*/
typedef struct _struct_listnode
{
    LinklistNode header;
    int v;      //保存与该结点相连的另一结点编号
    int w;      //保存该边的权值
}TListnode;

创建邻接链表:

/*
* 创建并返回有n个顶点的图
* 参数:
    data: 存放各顶点数据地址的指针数组
    n:    该图顶点的数目
* 返回值:
    如果成功,返回该图的有效地址;
    如果失败,返回NULL;
  */
LGraph* LGraph_Create(LVertex** v, int n)
{
    TLGraph *tgraph = NULL;
    if((v != NULL) && ( n > 0))
    {
        tgraph = (TLGraph*)malloc(sizeof(TLGraph));
        if(tgraph != NULL)
        {
            tgraph->count = n;
            //申请空间存放结点描述信息的地址
            tgraph->data = (LVertex**)malloc(sizeof(LVertex*) * n);
            //申请空间,并初始化为0,存放每个结点的链表地址
            tgraph->la = (Linklist**)calloc(n, sizeof(Linklist*));
            if((tgraph->data != NULL)&&(tgraph->la != NULL))
            {
                for(int i = 0; i < tgraph->count; i++)
                {
                    tgraph->data[i] = v[i];  //保存结点描述信息
                }
                int condition = 1;
                //为每个结点创建链表,并将地址保存在la地址数组中
                for(int i = 0; (i < tgraph->count) && (condition); i++)
                {
                        condition = condition && ((tgraph->la[i] = List_Create()) != NULL);
                }
            }
            else
            {
                //如果上述操作出现错误,则将所有资源释放,切记要销毁每个结点的链表
                if(tgraph->la != NULL)
                {
                    for(int i = 0; i < tgraph->count; i++)
                    {
                        List_Destroy(tgraph->la[i]);
                    }
                }
                free(tgraph->data);tgraph->data = NULL;
                free(tgraph->la);tgraph->la = NULL;
                free(tgraph);tgraph = NULL;
            }
        }
    }
    return tgraph;
}

添加和删除边:

/*
在graph所指图中的v1和v2之间加上边,且边的权为w
* 参数:
    graph:  指向图的指针
    v1:     顶点1
    v2:     顶点2
    w:      两顶点之间边的权值
* 返回值:
    如果成功,返回非0值
    如果失败,返回0
*/
int LGraph_AddEdge(LGraph* graph, int v1, int v2, int w)
{
    TLGraph *tgraph = (TLGraph*)graph;
    TListnode *node = NULL;
    int iret = (tgraph != NULL);
    iret = iret && ( 0 <= v1) && (v1 < tgraph->count);
    iret = iret && (0 <= v2) && (v2 < tgraph->count);
    iret = iret && (w > 0);
    iret = iret && ((node = (TListnode*)malloc(sizeof(TListnode))) != NULL);
    if(iret)
    {
        node->v = v2;
        node->w = w;
        List_Insert(tgraph->la[v1], (LinklistNode*)node, List_Length(tgraph->la[v1]));
    }
    return iret;
}

/*
将graph所指图中v1和v2之间的边删除,返回权值
* 参数:
    graph:  指向图的指针
    v1:     顶点1
    v2:     顶点2
* 返回值:
    如果成功,返回两顶点之间边的权值,该值非负
    如果失败,返回-1
*/
int LGraph_RemoveEdge(LGraph* graph, int v1, int v2)
{
    TLGraph *tgraph = (TLGraph*)graph;
    int iret = -1;
    int condition = (tgraph != NULL);
    condition = condition && (0 <= v1) && (v1 < tgraph->count);
    condition = condition && (0 <= v2) && (v2 < tgraph->count);
    if(condition)
    {
        if(tgraph->la != NULL)
        {
            TListnode *node = NULL;
            for(int i = 0; i < List_Length(tgraph->la[v1]); i++)
            {
                node = (TListnode*)List_Get(tgraph->la[v1], i);
                if(node != NULL)
                {
                    if(node->v == v2)
                    {
                        iret = node->w;
                        List_Delete(tgraph->la[v1], i);
                        free(node);
                        node = NULL;
                        break;
                    }
                }
            }
        }
    }
    return iret;
}

返回顶点度数(TD):

/*
 将graph所指图中v顶点的度数
* 参数:
    graph:  指向图的指针
    v:      顶点
* 返回值:
    如果成功,返回顶点v的度数,该值非负
    如果失败,返回-1
 */
int LGraph_TD(LGraph* graph, int v)
{
    TLGraph *tgraph = (TLGraph*)graph;
    int iret = -1;
    if((tgraph != NULL) && (0 <= v) && (v < tgraph->count))
    {
        if(tgraph->la != NULL)
        {
            iret = 0;
            TListnode *node = NULL;
            for(int i = 0; i < tgraph->count; i++)
            {
                for(int j = 0; i < List_Length(tgraph->la[i]); j++)
                {
                    node = (TListnode*)List_Get(tgraph->la[i], j);
                    if(node != NULL)
                    {
                        if(node->v == v)
                        {
                            iret++;
                        }
                    }
                }
            }
            iret += List_Length(tgraph->la[v]);
        }
    }
    return iret;
}

4、小结

这里写图片描述

5、完整源码下载

github地址:稍后放出。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值