关于图的存储方法 (静态邻接表、前向星、边集数组)

一、邻接矩阵(不多说了)  G[u][v]

二、邻接表

                  1、动态链表(指针)      一个数组表头(u)+ struct结点(v),相链,若有权值等信息再在结点里加相应域。

                  2、静态链表(数组)      first数组(模拟表头、u)+ 边集数组(编号e,u、v)+ next数组(模拟指针相指)。这个跟1看似有点区别(前者链的是点,后者链的是边),其实是没区别,因为要用数组实现链表,所以对1中所有结点实行e编号,意义就是“边”。

通常实现方法: 开五个数组 first[MAXN]; u[MAXM], v[MAXM], w[MAXM], next[MAXM]。

三、边集数组

就是把所有边放在一个数组里,这样就可以完成遍历所有边的操作了(很土吧= =)。通常要根据实际需要做一些辅助储存。

1、上面的数组实现邻接表就是边集数组再加上first数组和next数组。

2、前向星。跟1很相似的,区别是他对边集数组按u点(前一个端点)升序排序,使得由同一个点出发的边都集中在一起了。再加上辅助数组 f[MAXN](跟前面first数组类似的作用),存 结点i 出发的第一个边在边集数组里的位置。 

所以注意到,前向星其实就是做了一个紧缩存储的处理,并且通过一次排序,省掉了next数组(静态邻接表)。当然也可以不排序,多维护一个next数组。

通常实现方法:开四个数组 f[MAXN]; u[MAXM], v[MAXM], w[MAXM]。


附:

①静态邻接表+Dijkstra+heap

//  Dijkstra+静态邻接表
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;

#define MAXN 100
#define MAXM 100
#define INF 1<<30
typedef pair<int, int> pii;		//(dist[v], v)
priority_queue<pii, vector<pii>, greater<pii> > q;
int first[MAXN];
int u[MAXM], v[MAXM], w[MAXM], next[MAXM];
int dist[MAXN], ins[MAXN];	//  ins[]  是否在s集合中
int n, m;

void dijkstra(int st)
{
	for(int i=0; i<n; i++) dist[i] = i==st? 0: INF;
	memset(ins, 0, sizeof(ins));
	q.push(make_pair(dist[st], st));
//	ins[st] = 1;						//别跟spfa inq弄混,在优先队列里取出来才算是ins了
	while(!q.empty())
	{
		pii p = q.top();	q.pop();
		int x = p.second;
		if(!ins[x])
		{
			ins[x] = 1;
			for(int i=first[x]; i!=-1; i=next[i])
			{
				if(dist[v[i]] > dist[x]+w[i])		//relax
				{
					dist[v[i]] = dist[x] + w[i];
					q.push(make_pair(dist[v[i]], v[i]));
				}
			}
		}
	}//end of while
}

void read_graph()
{
	scanf("%d%d", &n, &m);
	memset(first, -1, sizeof(first));
	for(int i=0; i<m; i++)
	{
		scanf("%d%d%d", &u[i], &v[i], &w[i]);
		next[i] = first[u[i]];
		first[u[i]] = i;
	}
}

int main()
{
	read_graph();
	int st;
	dijkstra(scanf("%d", &st));
	for(int i=0; i<n; i++)
	{
		printf("[%d,%d]=%d\n", st, i, dist[i]);
	}
}

②静态邻接表+spfa

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
#define MAXN 100
#define MAXM 100
#define INF 1<<30
queue<int> q;
int first[MAXN], next[MAXM];
struct edge
{
	int u, v, w;
}a[MAXM];
int dist[MAXN], inq[MAXN];
int n, m;

void spfa(int st)
{
	for(int i=0; i<n; i++) dist[i] = i==st? 0: INF;
	memset(inq, 0, sizeof(inq));
	q.push(st);
	inq[st] = 1;					//反正马上就出队,这个inq可以不要
	while(!q.empty())
	{
		int u = q.front(); q.pop();
		inq[u] = 0;
		for(int e=first[u]; e!=-1; e=next[e])
		{
			int v = a[e].v;
			if(dist[v] > dist[u]+a[e].w)
			{
				dist[v] = dist[u]+a[e].w;
				if(!inq[v]) { q.push(v); inq[v] = 1; }		//inq=1 !!!!
			}
		}
	}
}

void read_graph()
{
	cin>>n>>m;
	memset(first, -1, sizeof(first));		//别忘了初始化 表头
	for(int e=0; e<m; e++)
	{
		cin>>a[e].u>>a[e].v>>a[e].w;
		next[e] = first[a[e].u];
		first[a[e].u] = e;
	}
}

int main()
{
	read_graph();
	int st;
	cin>>st;
	spfa(st);
	for(int i=0; i<n; i++)
	{
		printf("[%d,%d]=%d\n", st, i, dist[i]);
	}
}



阅读更多

没有更多推荐了,返回首页