图的实现

[复制链接]
发表于 2024-1-2 18:00:57 | 显示全部楼层 |阅读模式

(1) 邻接矩阵!
开一个二维数组 GG[i][j]表示边(i,j)的权。如果边(i,j)不存在,就令 G[i][j]=INF(当然,(i,i)不是一条边,G[i][i]也等于INF)。
邻接矩阵最大的缺点就是内存空间占用太大,内存浪费严重。
(2) 边目录!
设置三个数组 u[M]、v[M]、w[M],分别表示起点、终点和权。
一般情况下,从文件中读取的图都是用边目录来表示的。
(3) 邻接表(链表)!
用一个列表列出所有与现结点之间有边存在的结点名称。
struct edge
{  int u,v,w;  edge *next;
} mem[M];        // mem相当于动态内存分配。 int size=-1;
#define NEW(p) p=&mem[++size]; p->next=NULL
edge *adj[N];       // adj代表以i为起点的边。
……
memset(adj, 0, sizeof(adj)); for (int e=0; e<m; e++)
{  edge *p;  NEW(p);
cin>>(p->u)>>(p->v)>>(p->w);  p->next=adj[p->u];  adj[p->u]=p;
}
如果想检查从 a 出发的所有边,那么可以
for (edge *e=adj[a]; e!=NULL; e=e->next)
{
// e->u是起点,e->v是终点,e->w是权
}
(4) 邻接表(静态数组)! 注意,在这个“邻接表”里放置的元素是边的序号,不是点的序号。所以还要和边目录配合使用。
int first[N];       // first表示从u出发的第一条边的序号 int u[M],v[M],w[M], next[M];  // next[e]表示编号为e的下一条边的序号 ...... memset(first, -1, sizeof(first)); for (int e=0; e<m; e++)
{  cin>>u[e]>>v[e]>>w[e];  next[e]=first[u[e]];   // 插入一条边  first[u[e]]=e;
}
如果想检查从 a 出发的所有边,那么可以
for (int e=first[a]; e!=-1; e=next[e])
{
// u[e]是起点,v[e]是终点,w[e]是权
}
(5) 邻接表(STL)!
头文件:<vector>
这种邻接表也要和边目录配合使用。只需把(4)中的代码换成以下代码:
vector<int> g[N];   
// g表示从u出发的第i条边的序号
int u[M],v[M],w[M];     ......
for (int e=0; e<m; e++)
{  cin>>u[e]>>v[e]>>w[e];  g.push_back(e);
}
// 同样要和边目录配合使用
如果想检查从 a 出发的所有边,那么可以
for (int i=0; i<g[a].size(); i++)
{
int &e=g[a];
// u[e]是起点,v[e]是终点,w[e]是权
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表