几种建图的方法

存图的方法

1.邻接矩阵存图

利用数组来模拟各个点之间的关系:mp[a][b]=v ab的权值是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实现

1615854752040

通过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,就是13(有向)。

遍历代码:

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;
    }
posted @ 2021-03-16 22:47  RuanCat  阅读(321)  评论(0)    收藏  举报