当前位置: 首页 > article >正文

算法【邻接矩阵、邻接表、链式前向星建图】

一般建图的三种方式

1.邻接矩阵(适合点的数量不多的图)

2.邻接表(最常用的方式)

3.链式前向星(空间要求严苛情况下使用。比赛必用,大厂笔试、面试不常用)

邻接矩阵自是不用多说,邻接表就是每个点后面跟一个存储着从这个点出发的连接的点,如果边带权值,就存储一个数组。下面着重讲解链式前向星建图。

在链式前向星建图中,有3个数组,分别是,head、next、to。head数组,下标为点的编号,一般从1开始,值代表从下标编号的点开始遍历的第一条边的编号,初始化为0,代表还没有边。next数组,下标为边的编号,一般从1开始,值代表遍历完这条边后下一条边的编号,如果为0代表没有了。to数组,下标为边的编号,一般从1开始,值代表这条边指向的点的编号。如果是带权图,那么新加一个weight数组,下标为边的编号,一般从1开始,值代表这条边的权值。当我们得到一条边的信息:出度节点i、入度节点j,这里建不带权图,我们会有一个cnt变量记录当前的边的编号,这时,由出度节点得到head[i],将next[cnt]赋值为head[i],然后把head[i]更新为cnt,最后将to[cnt]赋值为j。如果有权值,将weight[cnt]赋值为权值。最后cnt加1。将所有边更新完,图便建立完成。

下面给出三种建图方法的代码。代码如下。

#include <iostream>
#include <vector>
using namespace std;
// 点和边的数量
int m = 11;
int n = 21;
// 邻接矩阵建图 不带权图
int graph1[12][12];
void build1_1(vector<vector<int>>& edges){
    for(int i = 0;i < n;++i){
        graph1[edges[i][0]][edges[i][1]] = 1;
        // graph1[edges[i][1]][edges[i][0]] = 1;
    }
}
// 邻接矩阵建图 带权图
void build1_2(vector<vector<int>>& edges){
    for(int i = 0;i < n;++i){
        graph1[edges[i][0]][edges[i][1]] = edges[i][2];
        // graph1[edges[i][1]][edges[i][0]] = edges[i][2];
    }
}
// 邻接表建图 不带权图
vector<vector<int>> graph2_1;
void build2_1(vector<vector<int>>& edges){
    vector<int> temp;
    for(int i = 0;i <= m;++i){
        graph2_1.push_back(temp);
    }
    for(int i = 0;i < n;++i){
        graph2_1[edges[i][0]].push_back(edges[i][1]);
        // graph2_1[edges[i][1]].push_back(edges[i][0]);
    }
}
// 邻接表建图 带权图
vector<vector<vector<int>>> graph2_2;
void build2_2(vector<vector<int>>& edges){
    vector<vector<int>> temp1;
    vector<int> temp2;
    for(int i = 0;i <= m;++i){
        graph2_2.push_back(temp1);
    }
    for(int i = 0;i < n;++i){
        temp2.push_back(edges[i][1]);
        temp2.push_back(edges[i][2]);
        graph2_2[edges[i][0]].push_back(temp2);
        temp2.clear();
        // temp2.push_back(edges[i][0]);
        // temp2.push_back(edges[i][2]);
        // graph2_2[edges[i][1]].push_back(temp2);
        // temp2.clear();
    }
}
// 链式前向星建图 不带权图
int Head[12] = {0};
int Next[22] = {0};
int To[22] = {0};
int cnt = 1;
void build3_1(vector<vector<int>>& edges){
    for(int i = 0;i < n;++i){
        Next[cnt] = Head[edges[i][0]];
        Head[edges[i][0]] = cnt;
        To[cnt] = edges[i][1];
        ++cnt;
        // Next[cnt] = Head[edges[i][1]];
        // Head[edges[i][1]] = cnt;
        // To[cnt] = edges[i][0];
        // ++cnt;
    }
}
// 链式前向星建图 带权图
int Weight[22] = {0};
void build3_2(vector<vector<int>>& edges){
    for(int i = 0;i < n;++i){
        Next[cnt] = Head[edges[i][0]];
        Head[edges[i][0]] = cnt;
        To[cnt] = edges[i][1];
        Weight[cnt] = edges[i][2];
        ++cnt;
        // Next[cnt] = Head[edges[i][1]];
        // Head[edges[i][1]] = cnt;
        // To[cnt] = edges[i][0];
        // Weight[cnt] = edges[i][2];
        // ++cnt;
    }
}

其中,点的编号和边的编号都是从1开始;默认建有向图,注释掉的代码是建无向图;m是点的数量,n是边的数量,当然这里这是做一个例子,具体情况具体修改即可。


http://www.kler.cn/a/291993.html

相关文章:

  • Flume 单机与集群部署详细教程
  • windows C#-异步编程概述(二)
  • python机器人Agent编程——多Agent框架的底层逻辑(上)
  • 校园二手交易网站毕业设计基于SpringBootSSM框架
  • ISP是什么?
  • 神经网络的正则化(一)
  • VUE3+DRF 网页天气卡片组件实现
  • Java项目: 基于SpringBoot+mysql在线文档管理系统(含源码+数据库+开题报告+答辩PPT+毕业论文)
  • 经验笔记:RPC与高性能NIO框架
  • 【软件测试专栏】自动化测试函数篇
  • 业务复杂度治理方法论--十年系统设计经验总结
  • 【Hot100】LeetCode—34. 在排序数组中查找元素的第一个和最后一个位置
  • pnpm、npm和nvm分别时什么,及区别?
  • Android架构组件:MVVM模式的实战应用于数据绑定技巧
  • shell脚本的变量与应用
  • 计算机网络11——数据库语法2
  • hyperf json-rpc
  • <meta name=“robots“ content=““>介绍
  • Linux下快速判断当前终端使用的是bash or csh
  • 操作系统:线程实现方式
  • 【赵渝强老师】MongoDB的存储引擎
  • WorkPlus安全即时通讯:端到端加密开启信息保密新时代
  • [大数据]Debug:常见错误集合
  • 【Python机器学习】NLP词频背后的含义——从词频到主题得分
  • 开源模型应用落地-qwen2-7b-instruct-LoRA微调-ms-swift-单机多卡-RTX 4090双卡(十四)
  • 微信小程序知识点(二)