第十一项目二 操作用邻接表存储的图

/*  
烟台大学 计算机与控制工程学院  
文件名称:用邻接表存储图 
作    者:胡德杰  
完成日期:2017年12月13号  
版 本 号:v1.1.36 
*/ 
#include <stdio.h>
#include <malloc.h>
#include "graph.h"

//返回图G中编号为v的顶点的出度
int OutDegree(ALGraph *G,int v)
{
    ArcNode *p;
    int n=0;
    p=G->adjlist[v].firstarc;
    while (p!=NULL)
    {
        n++;
        p=p->nextarc;
    }
    return n;
}

//输出图G中每个顶点的出度
void OutDs(ALGraph *G)
{
    int i;
    for (i=0; i<G->n; i++)
        printf("  顶点%d:%d\n",i,OutDegree(G,i));
}

//输出图G中出度最大的一个顶点
void OutMaxDs(ALGraph *G)
{
    int maxv=0,maxds=0,i,x;
    for (i=0; i<G->n; i++)
    {
        x=OutDegree(G,i);
        if (x>maxds)
        {
            maxds=x;
            maxv=i;
        }
    }
    printf("顶点%d,出度=%d\n",maxv,maxds);
}
//输出图G中出度为0的顶点数
void ZeroDs(ALGraph *G)
{
    int i,x;
    for (i=0; i<G->n; i++)
    {
        x=OutDegree(G,i);
        if (x==0)
            printf("%2d",i);
    }
    printf("\n");
}

//返回图G中是否存在边<i,j>
bool Arc(ALGraph *G, int i,int j)
{
    ArcNode *p;
    bool found = false;
    p=G->adjlist[i].firstarc;
    while (p!=NULL)
    {
        if(p->adjvex==j)
        {
            found = true;
            break;
        }
        p=p->nextarc;
    }
    return found;
}

int main()
{
    ALGraph *G;
    int A[7][7]=
    {
        {0,1,1,1,0,0,0},
        {0,0,0,0,1,0,0},
        {0,0,0,0,1,1,0},
        {0,0,0,0,0,0,1},
        {0,0,0,0,0,0,0},
        {0,0,0,1,1,0,1},
        {0,1,0,0,0,0,0}
    };
    ArrayToList(A[0], 7, G);
    printf("(1)各顶点出度:\n");
    OutDs(G);
    printf("(2)最大出度的顶点信息:");
    OutMaxDs(G);
    printf("(3)出度为0的顶点:");
    ZeroDs(G);
    printf("(4)边<2,6>存在吗?");
    if(Arc(G,2,6))
        printf("是\n");
    else
        printf("否\n");
    printf("\n");
    return 0;
}

知识点总结:操作用邻接表存储的图。

<think>好的,用户想了解邻接表存储方式和实现方法,数据结构中的相关。首先,我需要回忆一下邻接表的基本概念。邻接表的一种链式存储结构,适用于边数较少的稀疏,相比邻接矩阵更节省空间。根据之前的引用,引用[1]提到用于存储多对多关系,引用[2]详细说明了邻接表的结构,包括头结点和表结点的数量,以及与其他结构如十字链表的区别。引用[4]提供了具体的代码定义,可能需要参考这些结构来解释实现方法。 用户可能需要了解邻接表的结构组成,比如顶点数组和边链表。每个顶点对应一个链表,存储其邻接点。例如,无向中,一条边会出现在两个顶点的链表中,而有向则只在起点的链表中。引用[2]提到无向需要2e个表结点,这点需要注意。 接下来是实现的步骤,包括如何创建邻接表,添加删除顶点和边的操作。根据引用[4]中的代码定义,顶点存储在vertex数组中,每个VNode包含数据和指向第一个邻接点的指针。del_vertex操作需要找到顶点,删除所有与之相关的边,并调整其他顶点。这部分可能需要详细说明,特别是如何处理边的删除和链表的更新。 代码示例部分,用户可能需要看到具体的结构定义和函数实现,比如初始化、插入边、删除顶点等。要注意有向和无向的区别,比如插入边时是否需要双向处理。引用[3]提到创建邻接矩阵的函数,但这里需要转换为邻接表的实现。 最后,相关问题部分需要生成与邻接表相关的问题,比如优缺点、遍历方式、与其他结构的比较等。引用[2]提到了邻接矩阵和邻接表的空间对比,可以作为一个问题。应用场景也是一个好的问题方向,比如引用[1]中的结构应用。 需要确保回答符合系统指令,使用正确的中文和LaTeX格式,比如变量用$...$,独立公式用$$...$$。同时检查引用标记是否正确添加,例如邻接表节省空间的部分引用[2],结构定义引用[4]。 总结回答的结构:先解释邻接表的概念和组成,然后详细描述存储方式,接着是代码实现的关键步骤,最后生成相关问题。确保每个部分都有对应的引用支持,特别是实现细节部分参考引用[4]的代码结构。</think>### 邻接表存储方式及实现方法 #### 1. 邻接表的基本概念 邻接表的一种链式存储结构,由顶点表和边链表组成。每个顶点对应一个链表,链表中存储与该顶点直接相连的所有邻接顶点。这种结构特别适合存储**边稀疏的**,空间复杂度为$O(n+e)$(n为顶点数,e为边数)[^2]。 #### 2. 存储结构组成 - **顶点表(Vertex Array)** 使用数组存储顶点信息,每个元素包含: - 顶点数据(如`data`) - 指向第一条邻接边的指针(如`firstarc`)[^4] - **边链表(ArcNode)** 每个链表结点表示一条边,包含: - 邻接顶点在顶点表中的下标(`adjvex`) - 边权值或其他信息(`info`,可选) - 指向下一个邻接边的指针(`nextarc`) #### 3. 实现关键步骤 **1. 结构定义** 引用[^4]中的代码定义: ```c typedef struct ArcNode { int adjvex; // 邻接顶点下标 InfoPtr *info; // 边信息(如权重) struct ArcNode *nextarc; // 指向下一条边 } ArcNode; typedef struct VNode { VertexType data; // 顶点数据 ArcNode *firstarc; // 指向第一条邻接边 } VNode; typedef struct { VNode vertex[MAX_VERTEX_NUM]; // 顶点数组 int vexnum, arcnum; // 顶点数、边数 GraphType type; // 类型(有向/无向) } ListGraph; ``` **2. 添加边操作(示例)** ```c void add_edge(ListGraph *G, int v1, int v2) { // 创建新边结点 ArcNode *new_node = (ArcNode*)malloc(sizeof(ArcNode)); new_node->adjvex = v2; new_node->nextarc = G->vertex[v1].firstarc; G->vertex[v1].firstarc = new_node; // 若是无向,需反向添加 if (G->type == UDG) { ArcNode *reverse_node = (ArcNode*)malloc(sizeof(ArcNode)); reverse_node->adjvex = v1; reverse_node->nextarc = G->vertex[v2].firstarc; G->vertex[v2].firstarc = reverse_node; } } ``` **3. 删除顶点操作** 引用中的`del_vertex`实现逻辑: 1. 定位顶点下标`v_index` 2. 删除所有**以v为终点**的边(遍历所有顶点的边链表) 3. 删除顶点v的边链表 4. 调整顶点数组(后续顶点前移) #### 4. 邻接表 vs 邻接矩阵 | 特性 | 邻接矩阵 | 邻接表 | |--------------|--------------------------|----------------------------| | 空间复杂度 | $O(n^2)$ | $O(n+e)$ | | 查询边存在性 | $O(1)$ | $O(k)$(k为边链表长度) | | 适用场景 | 稠密 | 稀疏 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值