22计算机408考研—数据结构—邻接表

293 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第33天,点击查看活动详情

手把手教学考研大纲范围内图的存储和遍历 22考研大纲数据结构要求的是C/C++,笔者以前使用的都是Java,对于C++还很欠缺, 如有什么建议或者不足欢迎大佬评论区或者私信指出 初心是用最简单的语言描述数据结构

Talk is cheap. Show me the code. 理论到处都有,代码加例题自己练习才能真的学会

2.2、邻接表

​ 当一个图中,边的数量少 时(也叫做稀疏图),用邻接矩阵会很 浪费空间 ,这时候 邻接表 就出来了

查看源图像

邻接表结构:

查看源图像

头结点包含一个 顶点 和一个指向 边(表结点) 的指针

表结点包含一个 顶点 ,一个指向 下一条边(表结点) 的指针 和 边的权值(图没有权值)

Tips: 这里指向的边,都是 以当前 头结点 顶点 直接联系 的边

​ eg:

​ 比如这个以 V1 直接联系的点是 V4 和 V2 ,所以表结点是 V4 和 V2

无向图

查看源图像

有向图

查看源图像

解释:

0-4 代表 a-e

​ 邻接矩阵中,是以顶点为起点的关系(逆邻接矩阵,以顶点为终点的关系)

​ 0 -> 1 (a->b) 的边,权重 e1

​ 0 -> 2 (a->c) 的边,权重 e2

​ 0没有指向其他方向的边了

多分析分析这几个图,其实很容易懂得

邻接表示例代码

代码:
#include "iostream"

using namespace std;

#define MAXNum 100  //顶点数最大为100

typedef struct ArcNode {    //定义边结点结构体:顶点的邻点adjvex,边的权重,下一个边结点的指针
    int adjvex;
    int info;
    struct ArcNode *nextarc;
} ArcNode;

typedef struct VNode {  //定义表头结点结构体:顶点data,指向边结点的指针
    int data;
    ArcNode *firstarc;
} VNode, AdjList[MAXNum];   //AdjList 是表头结点的数组类型

typedef struct {    //定义邻接表结构体:表头结点数组,顶点数量和边数量
    AdjList vertices;
    int vexnum, arcnum;
} ALGraph;
    //找到顶点在表头结点的下标
int getGraphIndex(ALGraph G, int targetnode) {
    for (int i = 0; i < G.vexnum; i++) {
        if (G.vertices[i].data == targetnode) {
            return i;
        }
    }
    return -1;
}

    //创建邻接表
bool createGraph(ALGraph &G) {
    cout << "请输入顶点数量和边的数量" << endl;
    cin >> G.vexnum >> G.arcnum;    //输出顶点数量和边数量
    for (int i = 0; i < G.vexnum; i++) {    //输出顶点,并且设置指向的边结点为空
        cout << "请输入顶点的值" << endl;
        cin >> G.vertices[i].data;
        G.vertices[i].firstarc = NULL;
    }
    int v1, v2, i1, i2;
    for (int i = 0; i < G.arcnum; i++) {    //输入两个相邻的顶点
        cout << "请输入新建边相邻的两个结点" << endl;
        cin >> v1 >> v2;
        i1 = getGraphIndex(G, v1);  //找到两个顶点的下标
        i2 = getGraphIndex(G, v2);

        ArcNode *p1 = new ArcNode;  //创建p1边结点,让v1表头结点指向p1边结点
        p1->adjvex = v2;    //p1设置邻接点为v2
        p1->nextarc = G.vertices[i1].firstarc;  //采用头插法,如果采用尾插,每次都要循环到当前表头结点的最后一个末尾边结点才能插入
        G.vertices[i1].firstarc = p1;

        ArcNode *p2 = new ArcNode;  //与上面同理
        p2->adjvex = v1;
        p2->nextarc = G.vertices[i2].firstarc;
        G.vertices[i2].firstarc = p2;
    }
    return true;
}

    //输出邻接表
void printGraph(ALGraph G) {
    for (int i = 0; i < G.vexnum; i++) {
        cout << G.vertices[i].data << " :  ";
        ArcNode *temp = G.vertices[i].firstarc;
        while (temp != NULL) {
            cout << "下一个顶点:" <<  temp->adjvex << "  ";
            temp = temp->nextarc;
        }
        cout << "下一个顶点为空\n";
    }
}

int main() {
    ALGraph G;
    //输入样例:4 3 1 2 3 4 1 2 1 3 2 3
    createGraph(G);
    printGraph(G);
}

输入输出样例:
/home/a1439775520/CLionProjects/Graph/cmake-build-debug/Graph
请输入顶点数量和边的数量
4 3
请输入顶点的值
1
请输入顶点的值
2
请输入顶点的值
3
请输入顶点的值
4
请输入新建边相邻的两个结点
1 2
请输入新建边相邻的两个结点
1 3
请输入新建边相邻的两个结点
2 3
1 :  下一个顶点:3  下一个顶点:2  下一个顶点为空
2 :  下一个顶点:3  下一个顶点:1  下一个顶点为空
3 :  下一个顶点:2  下一个顶点:1  下一个顶点为空
4 :  下一个顶点为空

Process finished with exit code 0