[数据结构]:23-图(邻接表)(C语言实现)

目录

前言

已完成内容

图实现

01-开发环境

02-文件布局

03-代码

01-主函数

02-头文件

03-AdjListCommon.cpp

04-AdjListFunction.cpp

结语


前言

        此专栏包含408考研数据结构全部内容,除其中使用到C++引用外,全为C语言代码。使用C++引用主要是为了简化指针的使用,避免二重指针的出现。

已完成内容

[数据结构]:01-顺序表(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:02-单链表(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:03-栈(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:04-循环队列(数组)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:05-循环队列(链表)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:06-队列(链表带头结点)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:07-二叉树(无头结点)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:08-顺序查找(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:09-二分查找(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:10-二叉排序树(无头结点)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:11-冒泡排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:12-快速排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:13-插入排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:14-选择排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:15-堆排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:16-归并排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:17-双链表(带头结点)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:18-链栈(不带头结点)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:19-串KMP模式匹配(数组)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:20-线索二叉树(无头结点)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:21-并查集(数组)(C语言实现)_Chandni.的博客-CSDN博客

[数据结构]:22-图(邻接矩阵)(C语言实现)_Chandni.的博客-CSDN博客

图实现

01-开发环境

        语言:C/C++14

        编译器:MinGW64

        集成开发环境:CLion2022.1.3

02-文件布局

        请在CLion集成开发环境中创建C++可执行程序,否则无法运行,原因上面已解释。

                        ​​​​​              

03-代码

01-主函数

        用于测试。

// 默认为无向图,若为有向图或网,请适当修改
#include "./Head/AdjList.h"
#include "./Source/AdjListCommon.cpp"
#include "./Source/AdjListFunction.cpp"

int main() {
    ALGraph AdjList;
    InitGraph(AdjList);
    CreateGraph(AdjList);
    PrintGraph(AdjList);
    printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
    printf("-----------------------------------\n");

    // 判断两结点是否存在某边
    if (Adjacent(AdjList, 0, 1)) {
        printf("true\n");
    } else {
        printf("false\n");
    }
    if (Adjacent(AdjList, 2, 3)) {
        printf("true\n");
    } else {
        printf("false\n");
    }
    printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
    printf("-----------------------------------\n");

    // 列出与x邻接的边
    int Edge[MAXSIZE] = {-1, -1, -1, -1, -1};
    Neighbors(AdjList, 0, Edge);
    for (int i = 0; Edge[i] != -1; i++) {
        printf("%3d", Edge[i]);
    }
    printf("\n");
    printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
    printf("-----------------------------------\n");

    // 删除顶点
    DeleteVertex(AdjList, 0);
    PrintGraph(AdjList);
    printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
    printf("-----------------------------------\n");

    // 添加顶点
    InsertVertex(AdjList, 4);

    // 添加边
    AddEdge(AdjList, 1, 4);
    PrintGraph(AdjList);
    printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
    printf("-----------------------------------\n");

    // 删除边
    RemoveEdge(AdjList, 0, 1); // 不执行
    RemoveEdge(AdjList, 1, 2);
    PrintGraph(AdjList);
    printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
    printf("-----------------------------------\n");

    // 寻找第一个邻接点
    int Neighbor = FirstNeighbor(AdjList, 1);
    printf("FirstNeighbor = %d\n", Neighbor);
    printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
    printf("-----------------------------------\n");
    // 寻找除4之外的下一个邻接点
    Neighbor = NextNeighbor(AdjList, 1, 4);
    printf("FirstNeighbor = %d\n", Neighbor);
    printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
    printf("-----------------------------------\n");
    return 0;
}

02-头文件

        用于存储结构体和常量等。

//
// Created by 24955 on 2023-04-02.
// 默认为无向图,若为有向图或网,请适当修改
//

#ifndef INC_01_ADJACENTList_ADJList_H
#define INC_01_ADJACENTList_ADJList_H
// 头文件
#include <stdio.h>
#include <stdlib.h>

// 常量
#define MAXSIZE 5
typedef int VertexType;
typedef int EdgeType;

// 结构体-弧结点
typedef struct ArcNode {
    VertexType AdjVertex;
    struct ArcNode *next;
} ArcNode;
// 结构体-顶点
typedef struct {
    VertexType data;
    ArcNode *first;
} VertexNode, AdjL[MAXSIZE];
// 结构体-图
typedef struct {
    AdjL AdjList;
    int VexNum, ArcNum;
} ALGraph;
#endif //INC_01_ADJACENTList_ADJList_H

03-AdjListCommon.cpp

        用于存储初始化图、输出图等操作。

//
// Created by 24955 on 2023-04-02.
// 默认为无向图,若为有向图或网,请适当修改
//
// 初始化图
void InitGraph(ALGraph &Graph) {
    // 初始化顶点和边表
    for (int i = 0; i < MAXSIZE; i++) {
        Graph.AdjList[i].data = -1;
        Graph.AdjList[i].first = NULL;
    }
    Graph.VexNum = 0;
    Graph.ArcNum = 0;
}

// 创建图 - 主要方便测试,并非图的正确创建方式,应根据具体情况具体分析
void CreateGraph(ALGraph &Graph) {
    Graph.VexNum = 4;
    ArcNode *arcNode[4];
    for (int i = 0; i < Graph.VexNum; i++) {
        Graph.AdjList[i].data = i;
        ArcNode *p = (ArcNode *) malloc(sizeof(ArcNode));
        p->AdjVertex = i;
        p->next = NULL;
        arcNode[i] = p;
    }
    // 无向图
    /*
     *  1. 0->1->3
     *  2. 1->0->2
     *  3. 2->1
     *  4. 3->0*/
    Graph.AdjList[0].first = arcNode[1];
    arcNode[1]->next = arcNode[3];
    Graph.AdjList[1].first = arcNode[0];
    arcNode[0]->next = arcNode[2];
    // 顶点1已经使用过,应重新申请空间
    ArcNode *p = (ArcNode *) malloc(sizeof(ArcNode));
    p->AdjVertex = 1;
    p->next = NULL;
    Graph.AdjList[2].first = p;
    ArcNode *p1 = (ArcNode *) malloc(sizeof(ArcNode));
    p1->AdjVertex = 0;
    p1->next = NULL;
    Graph.AdjList[3].first = p1;
    Graph.ArcNum = 3;
}

// 输出邻接矩阵
void PrintGraph(ALGraph Graph) {
    for (int i = 0; i < MAXSIZE; i++) {
        printf("%2d\t", Graph.AdjList[i].data);
        ArcNode *p = Graph.AdjList[i].first;
        while (p) {
            printf("%2d", p->AdjVertex);
            p = p->next;
        }
        printf("\n");
    }
}

04-AdjListFunction.cpp

        用于存储图的基本操作。

//
// Created by 24955 on 2023-04-02.
// 默认为无向图,若为有向图或网,请适当修改
//
// 获取元素下标
int GetIndex(ALGraph Graph, VertexType x) {
    /*
     *  1. 获取元素真实下标*/
    int xIndex = -1;
    for (int i = 0; i < MAXSIZE; i++) {
        if (Graph.AdjList[i].data == x) {
            xIndex = i;
            break;
        }
    }
    return xIndex;
}

// 判断图中是否存在边<x,y>
bool Adjacent(ALGraph Graph, VertexType x, VertexType y) {
    /*
     *  1. 判断x->y是否存在边
     *  2. 存在返回true*/
    // 避免访问到不存在顶点
    if (x >= MAXSIZE || y >= MAXSIZE) {
        return false;
    }
    int xIndex = GetIndex(Graph, x);
    ArcNode *p = Graph.AdjList[xIndex].first;
    while (p) {
        if (p->AdjVertex == y) {
            return true;
        }
        p = p->next;
    }
    return false;
}

// 列出图中与顶点x邻接的边
void Neighbors(ALGraph Graph, VertexType x, int *Edge) {
    /*
     * 1. 遍历x所在行
     * 2. 用数组存储与之邻接的边另一个顶点*/
    int xIndex = GetIndex(Graph, x);
    // 未找到顶点x
    if (xIndex == -1) {
        return;
    }
    // 找到顶点x,统计x邻接顶点
    ArcNode *p = Graph.AdjList[xIndex].first;
    for (int i = 0; p; i++) {
        Edge[i] = p->AdjVertex;
        p = p->next;
    }
}

// 插入顶点x
void InsertVertex(ALGraph &Graph, VertexType x) {
    /*
     *  1. 插入,顶点个数+1*/
    if (Graph.VexNum == MAXSIZE) {
        return;
    }
    for (int i = 0; i < MAXSIZE; i++) {
        if (Graph.AdjList[i].data == -1) {
            Graph.AdjList[i].data = x;
            break;
        }
    }
    Graph.VexNum++;
}

// 删除边表某结点
void DeleteArcNode(ALGraph &Graph, int xIndex, VertexType x) {
    ArcNode *pre = Graph.AdjList[xIndex].first, *p;
    if (pre == NULL) {
        return;
    }
    // 若为第一个元素
    if (pre->AdjVertex == x) {
        Graph.AdjList[xIndex].first = pre->next;
        free(pre);
    } else {
        // 不是第一个元素
        p = pre->next;
        while (p) {
            if (p->AdjVertex == x) {
                pre->next = p->next;
                free(p);
                break;
            }
            p = p->next;
        }
    }
}

// 删除顶点x
void DeleteVertex(ALGraph &Graph, VertexType x) {
    /*
     *  1. 清除顶点,并修改顶点个数
     *  2. 清除边,并修改边个数*/
    // 清除顶点,将其值设为-1表示该顶点为空,并清除相应边
    int xIndex = GetIndex(Graph, x);
    if (xIndex == -1) {
        return;
    }
    ArcNode *p = Graph.AdjList[xIndex].first;
    while (p) {
        DeleteArcNode(Graph, xIndex, p->AdjVertex);
        p = Graph.AdjList[xIndex].first;
        Graph.ArcNum--;
    }
    Graph.AdjList[xIndex].data = -1;
    Graph.VexNum--;
    // 清除其余边
    for (int i = 0; i < MAXSIZE; i++) {
        if (Graph.AdjList[i].data != -1) {
            DeleteArcNode(Graph, i, x);
        }
    }
}

// 在边表中插入某顶点-尾部插入(也可头部插入)
void AddArcNode(ALGraph &Graph, int xIndex, VertexType x) {
    ArcNode *NewNode = (ArcNode *) malloc(sizeof(ArcNode));
    NewNode->AdjVertex = x;
    NewNode->next = NULL;
    ArcNode *p = Graph.AdjList[xIndex].first;
    if (p == NULL) {
        Graph.AdjList[xIndex].first = NewNode;
    } else {
        while (p->next) {
            p = p->next;
        }
        p->next = NewNode;
    }
    // 头部插入
//    NewNode->next = Graph.AdjList[xIndex].first;
//    Graph.AdjList[xIndex].first = NewNode;
}

// 添加边
void AddEdge(ALGraph &Graph, VertexType x, VertexType y) {
    /*
     *  1. 获取顶点值实际下标
     *  2. 插入边*/
    int xIndex = GetIndex(Graph, x);
    int yIndex = GetIndex(Graph, y);
    if (xIndex == -1 || yIndex == -1) {
        return;
    }
    // 添加边
    AddArcNode(Graph, xIndex, y);
    AddArcNode(Graph, yIndex, x);
    Graph.ArcNum++;
}

// 删除边
void RemoveEdge(ALGraph &Graph, VertexType x, VertexType y) {
    /*
     *  1. 获取顶点值实际下标
     *  2. 删除边*/
    int xIndex = GetIndex(Graph, x);
    int yIndex = GetIndex(Graph, y);
    if (xIndex == -1 || yIndex == -1) {
        return;
    }
    // 删除边
    DeleteArcNode(Graph, xIndex, y);
    DeleteArcNode(Graph, yIndex, x);
    Graph.ArcNum--;
}

// 寻找图中顶点x的第一个邻接点
int FirstNeighbor(ALGraph Graph, VertexType x) {
    /*
     *  1. 寻找第一个不为0的值,并返回顶点值*/
    int xIndex = GetIndex(Graph, x);
    if (xIndex == -1) {
        return -1;
    }
    ArcNode *p = Graph.AdjList[xIndex].first;
    if (p != NULL) {
        return p->AdjVertex;
    }
    return -1;
}

// 图的下一个邻接点-除y以外的下一个邻接点顶点号
int NextNeighbor(ALGraph Graph, VertexType x, VertexType y) {
    /*
     *  1. 寻找y之后第一个不为0的值,并返回顶点值*/
    int xIndex = GetIndex(Graph, x);
    if (xIndex == -1) {
        return -1;
    }
    // 寻找y之后的下一个邻接点
    ArcNode *p = Graph.AdjList[xIndex].first;
    while (p) {
        if (p->AdjVertex == y) {
            break;
        }
        p = p->next;
    }
    if (p) {
        p = p->next;
        if (p) {
            return p->AdjVertex;
        }
    }
    return -1;
}

结语

        此博客主要用于408考研数据结构C语言实现记录,内有不足,可留言,可讨论。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
邻接是一种数据结构,可以用来存储的顶点和边。在C语言中,可以使用链实现邻接。 首先,我们需要定义的顶点结构体和边结构体: ```c // 边的结构体 typedef struct Edge { int dest; // 边的目标顶点 struct Edge* next; // 指向下一条边的指针 } Edge; // 顶点的结构体 typedef struct Vertex { int value; // 顶点的值 Edge* head; // 指向第一条边的指针 } Vertex; ``` 然后,我们可以定义邻接的结构体,其中包含顶点数组和顶点数量: ```c typedef struct Graph { int numVertices; // 顶点数量 Vertex* vertices; // 顶点数组 } Graph; ``` 接下来,我们可以实现邻接的创建函数、添加边的函数和打印函数: ```c // 创建邻接 Graph* createGraph(int numVertices) { Graph* graph = (Graph*)malloc(sizeof(Graph)); graph->numVertices = numVertices; graph->vertices = (Vertex*)malloc(numVertices * sizeof(Vertex)); // 初始化顶点数组 for (int i = 0; i < numVertices; i++) { graph->vertices[i].value = i; graph->vertices[i].head = NULL; } return graph; } // 添加边到邻接 void addEdge(Graph* graph, int src, int dest) { Edge* newEdge = (Edge*)malloc(sizeof(Edge)); newEdge->dest = dest; newEdge->next = graph->vertices[src].head; graph->vertices[src].head = newEdge; // 无向需添加反向边 newEdge = (Edge*)malloc(sizeof(Edge)); newEdge->dest = src; newEdge->next = graph->vertices[dest].head; graph->vertices[dest].head = newEdge; } // 打印邻接 void printGraph(Graph* graph) { for (int i = 0; i < graph->numVertices; i++) { printf("顶点 %d 的边:", i); Edge* curr = graph->vertices[i].head; while (curr != NULL) { printf(" -> %d", curr->dest); curr = curr->next; } printf("\n"); } } ``` 现在,我们可以在主函数中使用这些函数来创建、添加边并打印邻接: ```c int main() { int numVertices = 5; Graph* graph = createGraph(numVertices); addEdge(graph, 0, 1); addEdge(graph, 0, 4); addEdge(graph, 1, 2); addEdge(graph, 1, 3); addEdge(graph, 1, 4); addEdge(graph, 2, 3); addEdge(graph, 3, 4); printGraph(graph); return 0; } ``` 运行以上代码,将输出如下结果: ``` 顶点 0 的边: -> 4 -> 1 顶点 1 的边: -> 4 -> 3 -> 2 -> 0 顶点 2 的边: -> 3 -> 1 顶点 3 的边: -> 4 -> 2 -> 1 顶点 4 的边: -> 3 -> 1 -> 0 ``` 这样,我们就完成了邻接的C语言实现。希望对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chandni.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值