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

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

参考: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;
}
时间: 2024-12-10 11:49:14

图的五种种存储方式【图论】的相关文章

图的邻接表存储方式的建立

图的邻接表存储方式,主要由表节点与头结点组成. 头结点中主要包含两个域: 1)存放顶点信息 2)存放与顶点相连的第一个表节点的指针 表节点中主要包含两个域: 1)存放相连的节点的序号 2)指向下一个节点的指针 #define MAXNUM 100; //表节点 typedef struct ArcNode{ int adjvex;//邻接顶点编号 struct ArcNode *next;//下一邻接顶点 }ArcNode; //头结点 typedef struct AdjList{ char

数据结构(二十八)图的五种存储结构

由于图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在内存中的物理位置来表示元素之间的关系,也就是说,图不可能用简单的顺序存储结构来表示. 多重链表的方式,即以一个数据域和多个指针域组成的结点表示图中的一个结点,尽管可以实现图结构,但是如果各个顶点的度数相差很大,按度数最大的顶点设计结点结构会造成很多存储单元的浪费,而若按每个顶点自己的度数设计不同的结点结构,又带来操作的不变. 图的类型主要有4种:无向图.有向图.无向网和有向网. 图的五种常见的存储结构:领接矩阵.领接表.十

android数据的五种存储方式

Android提供了5种方式存储数据 (1)使用SharedPreferences存储数据,它是Android提供的用来存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中.只能在同一个包内使用,不能在不同的包之间使用. SharedPreferences存储方式,它是Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码.其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入.存储目录/data/data/Package Name/

Android 五种存储方式个人总结

一 . 文件存储 FileOutputStream out = openFileOutput("data",Context.MODE_PRIVATE); BufferedWriter writer = new BufferedWriter(new OutputStream(out)); String  s ; writer.writer(s); 二. sharePreferences 存储 (键值对形式) 方法 1.    Context 类中的getSharedPreferences

图的几种存储方式

1,     邻接矩阵: struct MGraph { int ver[Max]; int arc[Max][Max]; int vers; int Eges; }; int Locate(MGraph G,int x) { for(int i=1;;i++) if(G.ver[i]==x) return i; } void CreateUDN_MG(MGraph &G) { cin>>G.vers>>G.Eges; for(int i=1;i<=G.vers;i+

iOS中常用的五种存储方式

今天讲四种,CoreData 这哥么我会专门讲.别急?? 属性列表(plist)归档 Preference(偏好设置) NSKeyedArchiver归档(NSCoding) SQLite3 Core Data https://segmentfault.com/a/1190000004389463

java 数据结构 图中使用的一些常用算法 图的存储结构 邻接矩阵:图的邻接矩阵存储方式是用两个数组来标示图。一个一位数组存储图顶点的信息,一个二维数组(称为邻接矩阵)存储图中边或者弧的信息。 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 实例如下,左图是一个无向图。右图是邻接矩阵表示:

以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合. 无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示. 对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D}:边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}: 有向图:若

android五种数据存储方式

在Android中提供了如下五种数据存储方式: SharedPreferences 文件存储 SQLite数据库方式 内容提供器(ContentProvider) 网络存储 下面具体介绍一下这五种数据存储方式的用法. 1. SharedPreferences SharedPreferences是android平台上的一个轻量级存储类,主要保存一些常用的配置信息.可以保存long.int.String类型数据. SharedPreferences以键值对方式读取和存入,最终会以XML方式保存数据,

图的存储方式

昨天 听caicai讲了几种关于图的存储方式 又学了好多  家有caicai 如有一宝 -> 转自 晓爷 下面 我所讲的 都是基于 有向图的建图方式 i: map[a][b] ---最基础的邻接矩阵  直接用二维数组 ii: 1 struct graph 2 { 3 int num; // ---指向 下一个顶点 ( 表示当前已经与 该顶点相邻的个数 ) 4 int next[x]; // -- 与 该顶点 第( x+1 )个相邻的点的标号 5 int dist[x]; // -- 与 该顶点