用邻接表存储图

结构示意图:

VNode数组(顶点表):

vertices[1] --> [2] --> NULL
                 ↑
                ArcNode:表示1连接到2

vertices[2] --> [3] --> [1] --> NULL
                 ↑      ↑
               2连3   2连1

vertices[3] --> [2] --> NULL
                 ↑
               3连2
 

定义代码:

//边结点结构体
struct ArcNode {        // 表示一条边(h-k)
    int adjvex;         // 它连接的“邻居”的编号(下标)
    int data;           // 实际编号(用于输出)
    ArcNode *nextarc;   // 指向下一条边(邻居)
};
//顶点结构体
struct VNode {
    int data;           // 顶点本身的编号(1, 2, ..., n)
    ArcNode *firstarc;  // 指向第一个邻接的边
};

struct ALGraph {
    VNode vertices[MVNum]; // 顶点数组
    int vexnum;             // 顶点数
    int arcnum;             // 边数
};

总之就是,存两个东西,一个是边结点,一个是顶点。

实例:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAX_VEX 100  // 最大顶点数

// 边结点定义
typedef struct ArcNode {
    int adjvex;                  // 邻接顶点编号
    struct ArcNode* nextarc;    // 指向下一个边结点
} ArcNode;

// 顶点结点定义
typedef struct VNode {
    int data;                   // 顶点编号或名称
    ArcNode* firstarc;          // 指向第一条边
} VNode;

// 图定义
typedef struct {
    VNode vertices[MAX_VEX];
    int vexnum;     // 当前顶点数
    int arcnum;     // 当前边数
} ALGraph;

// 查找顶点下标
int LocateVex(ALGraph* G, int v) {
    for (int i = 0; i < G->vexnum; i++) {
        if (G->vertices[i].data == v)
            return i;
    }
    return -1;
}

// 添加顶点
void AddVertex(ALGraph* G, int v) {
    G->vertices[G->vexnum].data = v;
    G->vertices[G->vexnum].firstarc = NULL;
    G->vexnum++;
}

// 添加边
void AddEdge(ALGraph* G, int v1, int v2) {
    int i = LocateVex(G, v1);
    int j = LocateVex(G, v2);
    if (i == -1 || j == -1) return;

    ArcNode* p1 = (ArcNode*)malloc(sizeof(ArcNode));
    p1->adjvex = j;
    p1->nextarc = G->vertices[i].firstarc;
    G->vertices[i].firstarc = p1;

    ArcNode* p2 = (ArcNode*)malloc(sizeof(ArcNode));
    p2->adjvex = i;
    p2->nextarc = G->vertices[j].firstarc;
    G->vertices[j].firstarc = p2;

    G->arcnum++;
}

// 删除边
void RemoveEdge(ALGraph* G, int v1, int v2) {
    int i = LocateVex(G, v1);
    int j = LocateVex(G, v2);
    if (i == -1 || j == -1) return;

    ArcNode **p = &G->vertices[i].firstarc;
    while (*p) {
        if ((*p)->adjvex == j) {
            ArcNode* temp = *p;
            *p = (*p)->nextarc;
            free(temp);
            break;
        }
        p = &(*p)->nextarc;
    }

    p = &G->vertices[j].firstarc;
    while (*p) {
        if ((*p)->adjvex == i) {
            ArcNode* temp = *p;
            *p = (*p)->nextarc;
            free(temp);
            break;
        }
        p = &(*p)->nextarc;
    }

    G->arcnum--;
}

// 删除顶点
void RemoveVertex(ALGraph* G, int v) {
    int i = LocateVex(G, v);
    if (i == -1) return;

    // 删除所有与该顶点相连的边
    while (G->vertices[i].firstarc) {
        int adj = G->vertices[i].firstarc->adjvex;
        RemoveEdge(G, v, G->vertices[adj].data);
    }

    // 移动后面的顶点到当前位置
    for (int k = i; k < G->vexnum - 1; k++) {
        G->vertices[k] = G->vertices[k + 1];
    }
    G->vexnum--;

    // 更新所有邻接点中的编号
    for (int m = 0; m < G->vexnum; m++) {
        ArcNode* p = G->vertices[m].firstarc;
        while (p) {
            if (p->adjvex > i)
                p->adjvex--;
            p = p->nextarc;
        }
    }
}

// 遍历图(DFS)
bool visited[MAX_VEX];
void DFS(ALGraph* G, int v) {
    printf("%d ", G->vertices[v].data);
    visited[v] = true;

    ArcNode* p = G->vertices[v].firstarc;
    while (p) {
        if (!visited[p->adjvex])
            DFS(G, p->adjvex);
        p = p->nextarc;
    }
}

// 初始化图
void InitGraph(ALGraph* G) {
    G->vexnum = 0;
    G->arcnum = 0;
}

// 示例程序
int main() {
    ALGraph G;
    InitGraph(&G);

    // 添加顶点
    AddVertex(&G, 1);
    AddVertex(&G, 2);
    AddVertex(&G, 3);
    AddVertex(&G, 4);

    // 添加边
    AddEdge(&G, 1, 2);
    AddEdge(&G, 2, 3);
    AddEdge(&G, 3, 4);

    printf("DFS遍历:");
    for (int i = 0; i < G.vexnum; i++)
        visited[i] = false;
    DFS(&G, 0);  // 从第0个顶点开始
    printf("\n");

    printf("删除边 (2, 3)\n");
    RemoveEdge(&G, 2, 3);

    printf("删除顶点 2\n");
    RemoveVertex(&G, 2);

    printf("DFS遍历:");
    for (int i = 0; i < G.vexnum; i++)
        visited[i] = false;
    DFS(&G, 0);
    printf("\n");

    return 0;
}



注意:

G->vertices[] 这个数组的下标是从 0 开始的,但你在添加顶点时传入的顶点编号 v,可能是从 1 开始的

数组下标(实际存储)顶点编号(你输入)
vertices[0]顶点编号 1
vertices[1]顶点编号 2
vertices[2]顶点编号 3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值