图的表示方法

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

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

邻接表:

这个只用文字有点解释不清,上图片(图片来源:https://blog.youkuaiyun.com/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.youkuaiyun.com/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;
}

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值