几种建图的方法
存图的方法
1.邻接矩阵存图
利用数组来模拟各个点之间的关系:mp[a][b]=v a到b的权值是v
如图(无向图):
| mp | 0 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 3 | 0 | 2 | 1 |
| 2 | 0 | 3 | 0 | 1 | 0 | 0 |
| 3 | 0 | 0 | 1 | 0 | 2 | 2 |
| 4 | 0 | 2 | 0 | 2 | 0 | 0 |
| 5 | 0 | 0 | 0 | 2 | 0 | 0 |
2.邻接表存图
邻接表,存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。
(1).用vector实现
通过v[a].push_back(b)的方式来存储各个点之间的关系
| head(vector[x]) | |||
|---|---|---|---|
| 1-> | 2-> | 5-> | 4->null |
| 2-> | 1-> | 3->null | |
| 3-> | 2-> | 4-> | 5->null |
| 4-> | 1-> | 3->null | |
| 5-> | 1-> | 3->null |
代码:
struct node{
int to,w;
};
vector<node>v[MAX];
......
for(int i=1;i<=n;i++){//存图
int x,y,w;
cin>>x>>y>>w;
v[x].to.push_back(y);
v[x].w.push_back(w);
}
for(int i=1;i<=n;i++){
for(vector<node>:: iterator k = v[i].begin();k!=v[i].end();k++){
cout<<i<<" "<<k[i].to<<" "<<k[i].w<<"\n";
}
}
(2).用静态链表实现<链式前向星>
参考以及部分引用:(https://blog.csdn.net/sugarbliss/article/details/86495945) (在此基础上建立自己的理解)
void add_edge(int u, int v, int w)//加边,u起点,v终点,w边权
{
edge[cnt].to = v; //终点
edge[cnt].w = w; //权值
edge[cnt].next = head[u];//以u为起点上一条边的编号,也就是与这个边起点相同的上一条边的编号
head[u] = cnt++;//更新以u为起点上一条边的编号
}
分别给这些方向加上编号,id相当于head[i]的值
//像这样表示的就是:
u v w
5 7
1 2 1 id=0
2 3 2 id=1
3 4 3 id=2
1 3 4 id=3
4 1 5 id=4
1 5 6 id=5
4 5 7 id=6
看到上方代码:
对于1 2 1这条边:edge[0].to = 2; edge[0].next = -1; head[1] = 0;
对于2 3 2这条边:edge[1].to = 3; edge[1].next = -1; head[2] = 1;
对于3 4 3这条边:edge[2].to = 4; edge[2],next = -1; head[3] = 2;
对于1 3 4这条边:edge[3].to = 3; edge[3].next = 0; head[1] = 3;
对于4 1 5这条边:edge[4].to = 1; edge[4].next = -1; head[4] = 4;
对于1 5 6这条边:edge[5].to = 5; edge[5].next = 3; head[1] = 5;
对于4 5 7这条边:edge[6].to = 5; edge[6].next = 4; head[4] = 6;
那么我们把每个开头的点分个类:
1
1 2 1 id=0
1 3 4 id=3
1 5 6 id=5
2
2 3 2 id=1
3
3 4 3 id=2
4
4 1 5 id=4
4 5 7 id=6
通过上表的观察我们会发现:
每一个数字集合从head最大的值开始:
head[4]=6 , head[3]=2 , head[2]=1 , head[1]=5
假如遍历“1”:
对于1 5 6这条边:edge[5].to = 5; edge[5].next = 3; head[1] = 5;
对于1 3 4这条边:edge[3].to = 3; edge[3].next = 0; head[1] = 3;
对于1 2 1这条边:edge[0].to = 2; edge[0].next = -1; head[1] = 0;
也就是:i=1时,head[1]=5 , edge[5].next=3 , edge[5].to=5
理解一下:head[1]是指向这个数字集合的最后一个记录的元素,edge[i].next相当于指向下一个该集合的元素的id , edge[i].to 就是这个集合 (1的集合) 到 edge[i].to的点 如edge[3].to=3,就是1到3(有向)。
遍历代码:
for(int i = 1; i <= n; i++)//编号为n的集合(起点)
{
cout << i << endl;
for(int j = head[i]; j != -1; j = edge[j].next)
{
cout << i << " " << edge[j].to << " " << edge[j].w << endl;
}
cout << endl;
}

浙公网安备 33010602011771号