码迷,mamicode.com
首页 > 其他好文 > 详细

图的五种种存储方式【图论】

时间:2014-12-23 21:11:42      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:

运用三种方式来实现图的存储,以适应不同的情况。

参考:ACM-ICPC程序设计系列——图论及应用

方式1:邻接矩阵

邻接矩阵是表示图的数据结构中最简单也是最常用的一种。

实现:二维数组Map[MAXN][MAXN],Map[i][j]表示点i到点j的距离。

初始化:Map[i][i] = 0,Map[i][j] = INF(i!=j),读入数据Map[i][j] = w。

时间复杂度:初始化O(n^2),建图需要O(m),总时间复杂度O(n^2)。

优缺点:简单直观,可直接查询点i和点j之间是否有边;遍历效率低,不

能存储重编;初始化效率低;大图开销大,适合存储点少的稠密图。

方式2:前向星

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 100;
const int MAXM = 100;
int head[MAXN];//存储起点为i的第一条边的位置
struct node
{
    int from;//起点
    int to;//终点
    int w;//权值
};
node edge[MAXM];

bool cmp(node a,node b)//边排序
{
    if(a.from == b.from && a.to == b.to)
        return a.w < b.w;
    if(a.from == b.from)
        return a.to < b.to;
    return a.from < b.from;
}

int main()
{
    int n,m;
    cin >> n >> m;
    for(int i = 0; i < m; i++)
    {
        cin >> edge[i].from >> edge[i].to >> edge[i].w;
    }
    sort(edge,edge+m,cmp);
    memset(head,-1,sizeof(head));
    head[edge[0].from] = 0;
    for(int i = 1; i < m; i++)//确定起点为i的第一条边位置
    {
        if(edge[i].from != edge[i-1].from)
            head[edge[i].from] = i;
    }

    for(int i = 1; i <= n; i++)//遍历图
    {
        //k为第i个结点边的起始位置
        for(int k = head[i]; edge[k].from == i && k < m; k++)
        {
            cout << edge[k].from << ' ' << edge[k].to << ' ' << edge[k].w << endl;
        }
    }

    return 0;
}
/*
7 8
1 1 1
1 3 1
1 3 2
3 5 1
3 6 1
4 6 1
2 4 1
1 2 1

*/

方式3:邻接表——动态建表

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 100;

struct EdgeNode<span style="white-space:pre">		</span>//邻接表节点
{
    int to;<span style="white-space:pre">		</span>//终点
    int w;<span style="white-space:pre">		</span>//权值
    EdgeNode *next;<span style="white-space:pre">	</span>//指向下一条边的指针
};

struct VNode<span style="white-space:pre">		</span>//起点表节点
{
    int from;<span style="white-space:pre">		</span>//起点
    EdgeNode *first;<span style="white-space:pre">	</span>//邻接表头指针
};

VNode Adjlist[MAXN];<span style="white-space:pre">	</span>//整个图的邻接表


int main()
{
    int n,m,x,y,w;
    cin >> n >> m;
    for(int i = 0; i < m; i++)//读入图
    {
        cin >> x >> y >> w;
        EdgeNode *p = new EdgeNode();
        p->to = y;
        p->w = w;
        p->next = Adjlist[x].first;
        Adjlist[x].first = p;
    }
    cout << endl;
    for(int i = 1; i <= n; i++)//遍历图
    {
        for(EdgeNode *k = Adjlist[i].first; k != NULL; k = k->next)
            cout << i << ' ' << k->to << ' ' << k->w << endl;
    }
    return 0;
}
方式4:邻接表——vector模拟链表实现

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 100;
const int MAXM = 100;

struct EdgeNode<span style="white-space:pre">		</span>//边表节点类型
{
    int to;<span style="white-space:pre">		</span>//终点
    int w;<span style="white-space:pre">		</span>//权值
};
vector<EdgeNode> Map[MAXN];


int main()
{
    EdgeNode e;
    int n,m,x,y,w;
    cin >> n >> m;
    for(int i = 0; i < m; i++)<span style="white-space:pre">	</span>//读入图
    {
        cin >> x >> y >> w;
        e.to = y;
        e.w = w;
        Map[x].push_back(e);
    }

    cout << endl;
    for(int i = 1; i <= n; i++)<span style="white-space:pre">	</span>//遍历图
    {
        for(vector <EdgeNode>::iterator k = Map[i].begin(); k!=Map[i].end(); k++)
        {
            EdgeNode t = *k;
            cout << i << ' ' << t.to << ' ' << t.w << endl;
        }
    }
    return 0;
}
方式5:邻接表——链式前向星★

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 100;
const int MAXM = 100;

int head[MAXN];
struct EdgeNode
{
    int to;
    int w;
    int next;
};
EdgeNode Edges[MAXM];

int main()
{
    int n,m,x,y,w;
    cin >> n >> m;
    memset(head,-1,sizeof(head));

    for(int i = 0; i < m; i++)
    {
        cin >> x >> y >> w;
        Edges[i].to = y;
        Edges[i].w = w;
        Edges[i].next = head[x];
        head[x] = i;
    }

    cout << endl;
    for(int i = 1; i <= n; i++)
    {
        for(int k = head[i]; k!= -1; k = Edges[k].next)
            cout << i << ' ' << Edges[k].to << ' ' << Edges[k].w << endl;
    }

    return 0;
}






图的五种种存储方式【图论】

标签:

原文地址:http://blog.csdn.net/lianai911/article/details/42108099

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!