图的表示方法

如何表示一个图:人类的智慧是无穷的,其实有许多种,不过最常用的有1.邻接矩阵 2.邻接表。

邻接矩阵:比较好理解的一种形式,假如有n个点,那么就建立一个n*n的矩阵G[n][n],如果第i个点与第j个点相连,那么在矩阵中表示为G[i][j]=w;w为它的权值,没有权值根据题意可表示为0或极大值。

邻接表:

这个只用文字有点解释不清,上图片(图片来源:https://blog.csdn.net/ma_chen_qq/article/details/73441633):

其实就是把每个顶点的邻边串起来,形成一条链

怎么表示呢?

1.用超级数组vector<int>G[n]来表示(我也不知道用这种方式表示到底是不是邻接表,但他非常的简单,并且与邻接表也很像)

#include <iostream>
#include <vector>
#include <list>

using namespace std;

static const int maxn=1000;
vector<int> G[maxn];

int main()
{

    int n,m;//n为点的个数,m为边的个数
    cin>>n>>m;
    while(m--)
    {
        int u,v;
        cin>>u>>v;
        G[u].push_back(v);
       // G[v].push_back(u);//无向图得加这个
    }

    cout<<"*****************"<<endl;
    for(int i=0;i<=n;i++){
        cout<<i<<"-";
       for(int j=0;j<G[i].size();j++)
       cout<<G[i][j]<<"-";
       cout<<endl;
    }

    return 0;
}

2.用链表来表示(用结构体表示的链表,写法上有点麻烦)

#include <iostream>
#include <cstdio>

using namespace std;

struct edge{
    int toppoint;
    int weight;
    edge* next1;
    friend bool operator<(const edge &a1,const edge& a2)
    {
        return a1.weight>a2.weight;
    }
};//边集
struct top_pointlist{
    edge * edge1;
};//顶点集
struct Graph_List{
    int toppoint_number;//点的数目
    int edge_number;//边的数目
    top_pointlist*list;//顶点列表
}g1;
void creatGraph(Graph_List&g)
{
    cin>>g.toppoint_number>>g.edge_number;
    g.list=new top_pointlist[g.toppoint_number];//代表顶点集这个数组的指针
    for(int i=0;i<g.toppoint_number;i++)//初始化
    {
        g.list[i].edge1=NULL;
    }
    for(int i=0;i<g.edge_number;i++)
    {
        int start;
        int end;
        int weight;
        cin>>start>>end>>weight;
        edge*next=new edge;
        next->toppoint=end;
        next->weight=weight;
        next->next1=NULL;
        if(g.list[start].edge1==NULL) g.list[start].edge1=next;
        else
        {
            edge* temp;
            temp=g.list[start].edge1;
            while(temp->next1)
            {
                temp=temp->next1;
            }//不断地往下找,找到后接上
            temp->next1=next;
        }
        /*无向图
        edge*next2=new edge;
        next2->toppoint=start;
        next2->weight=weight;
        next2->next1=NULL;
        if(g.list[end].edge1==NULL) g.list[end].edge1=next2;
        else
        {
            edge* temp;
            temp=g.list[end].edge1;
            while(temp->next1)
            {
                temp=temp->next1;
            }
            temp->next1=next2;
        }
        */
    }
}
void print(Graph_List g)
{
    for(int i=0;i<g.toppoint_number;i++)
    {
        edge*next;
        next=g.list[i].edge1;
        while(next)
        {
            cout << i<<"-"<< next->toppoint <<"("<<next->weight <<")"<< "-";
            next = next->next1;
        }
        cout<<"<"<<endl;
    }
}
int main()
{
    creatGraph(g1);
    print(g1);
    return 0;
}

3.用前向星(这部分有的讲解来源于http://blog.csdn.net/acdreamers/article/details/16902023  这个博客已经讲得很清楚了)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

static const int maxn=100;
typedef pair<int,int>pii;

int len[maxn],head[maxn];
pii edge[maxn];
//用len[i]来记录所有以i为起点的边在数组中的存储长度.
//用head[i]记录以i为边集在数组中的第一个存储位置.
//边集合
//注意数组的大小,len,head,edge的大小都以边的数目为准
int main()
{
    memset(len,0,sizeof(len));//初始化长度
    memset(head,-1,sizeof(head));//初始化点的位置
    int n,m;//n是点的数目,m是边的数目
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int u,v;
        pii x;
        cin>>u>>v;
        x=make_pair(u,v);
        edge[i]=x;
        len[u]++;
    }
    sort(edge,edge+m);
    cout<<"*****************"<<endl;
    for(int i=m-1;i>=0;i--)
    {
        head[edge[i].first]=i;
        cout<<edge[i].first<<"-"<<i<<" ";
    }
    cout<<endl<<"**********************"<<endl;
    for(int i=0;i<m;i++)
    {
        cout<<edge[i].first<<" "<<edge[i].second<<endl;
    }
    cout<<"****************"<<endl;
    for(int i=1;i<=n;i++)
    {
        cout<<head[i]<<"-"<<len[i]<<" ";
    }
    return 0;
}

4.用链式前向星

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

static const int maxn=100;
typedef pair<int,int>pii;

struct Edge{
    int w;//权值
    int end;//终点
    int next;//下一条边的位置
}edge[maxn<<1];//边的集合
int head[maxn];//顶点的第一条边所在的位置
int cnt=0;
void add(int u,int v,int w)
{
    edge[cnt].w=w;
    edge[cnt].end=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
int main()
{
    int u,v,n=5,m=7;//n为点的个数,m为边的个数
    memset(head,-1,sizeof(head));
    while(m--)
    {
        cin>>u>>v;
        add(u,v,1);
    }
    cout<<"*******************"<<endl;
    for(u=1;u<=n;u++)
    for(int i=head[u];i!=-1;i=edge[i].next)
    cout<<u<<"-"<<edge[i].end<<endl;
    return 0;
}

我会的就这么几种了,以后还有会继续更新……

 

版权声明:本文为qq_42370259原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_42370259/article/details/82015430

智能推荐

(数据结构)有向图的十字链表(Orthogonal List)表示方法

十字链表(Orthogonal List)是有向图的另一种链式存储结构,可以看成是将有向图的邻接表和逆邻接表相结合起来得到的一种链表。 之前发过的一篇文章:图的邻接表(Adjacency List)表示方法 分析有向图的邻接表表示法存在的问题: 虽然邻接表表示可以方便计算某个节点的出度,但不方便计算它的入度 可以方便找到所有从该某个点出发的边,但不方便找到所有指向某个顶点的边 为了解决这样的问题,...

人工智能基础-数学方法-形式逻辑

1956 年召开的达特茅斯会议宣告了人工智能的诞生。在人工智能的襁褓期,各位奠基者们,包括约翰·麦卡锡、赫伯特·西蒙、马文·明斯基等未来的图灵奖得主,他们的愿景是让“具备抽象思考能力的程序解释合成的物质如何能够拥有人类的心智”。 通俗地说,理想的人工智能应该具备抽象意义上的学习、推理与归纳能力,其通用性将远远强于解决国际象棋或是围棋...

P3397 地毯——题解2020.10.3

P3397 地毯 思路分析 定义一个二维数组 a[ ][ ]存放每个点覆盖地毯的个数,下标表示每个点的坐标; 设置一个二重循环依次遍历每个地毯覆盖的坐标范围,使地毯覆盖范围内点的值+1; 打印出该二维数组 a[ ][ ]即为本题答案; 注意事项 由题可知:对于20%的数据,有 n≤50,m≤100;对于100%的数据,有 n,m≤1000;所以数组定义为a[1003][1003]...

反射注解案例

1、反射案例: 需求 写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法 实现: 配置文件 反射 步骤: 创建对象 将需要创建的对象的全类名和需要执行的方法定义在配置文件中 在程序中加载读取配置文件 使用反射技术来加载类文件进内存 执行方法 第一步:Person类(创建对象) 第二步:配置文件 pro.properties(将需要创...

lambert与half lambert模型逐顶点和逐片元的漫反射光照

兰伯特模型 逐顶点光照 逐片元光照: 效果对比:左边为逐片元光照。右边为逐顶点光照。右边明暗交界处有较明显的锯齿 半兰伯特光照模型 兰伯特模型的一个问题就是背光面只有一种颜色,缺乏立体感。Half Lambert用于解决这个问题 半兰伯特模型公式: 与兰伯特模型的差别主要在于不同于将背光面光都设为0,它将背光的光也即负值也映射到[0,1]区间。避免了背光的颜色只有0这一种值。需要注意的是,half...

猜你喜欢

[React官网入门教程]三子棋游戏完整代码

入门教程: 认识 React 最终效果 完整代码 index.css部分 index.css部分...

票据打印机-ESC/POS指令使用

给打印机输入串口命令,是打印机处于一种状态,然后就能干你想让他干的活了.百度ESC/POS文档随便拿一个正规的都一样,就不在这里放地址了,拿到这个文档以后代码的编写我只举一个例子,其它的模式也都一样 比如说这个功能为初始化打印机,他有三种输入模式,第一种是ASCII码(ESC @),第二种是Hex也就是16进制数(1B 40),第三种Decimal十进制数(27 64),我以16进制为例,那么他的...

JDBC工具类抽取

以下内容为观看黑马教学视频后仿写 新建一个JAVA Project,目录结构如下:    jdbc配置文件 jdbc.properties jdbc工具类  JDBCUtil.java 测试程序 MainTest.java 数据库中数据如下: 执行测试程序,运行结果如下:...

如何根据CIFAR-10的格式制作自己的数据集(C/C++版)

首先特别感谢博主 @yhl_leo 关于CIFER-10数据集可查看官方介绍,存储信息介绍如下: 不啰嗦,直接上代码实例,图片如何存储为二进制格式的三个代码文件如下: 相应的代码及备注依次如下: 本人转换后的结果如下: 最后,将数据放入CIFAR-10模型中,并修改一下部分参数,效果还不错!...

自己整理的docker常用目录和知识(持续更新完善)

目录 1.docker简介 2.docker安装 3.docker常用命令 4.docker镜像 5.docker容器数据卷 6.dockerFile       1.docker简介 2.docker安装 3.docker常用命令 1.帮助命令 查看版本信息:docker version 显示 docker 系统信息,包括镜像和容器数:docker info 帮助:...