如何表示一个图:人类的智慧是无穷的,其实有许多种,不过最常用的有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;
}
我会的就这么几种了,以后还有会继续更新……