图的定义
图是由点和连接点的边组成的,树是一种特殊的图,是一种连通无环图。
图的分类
我们可以根据边有无方向、有无权值、有无环路进行分类:
- 无向无权图,边没有权值、没有方向
- 有向无权图,边没有权值、有方向
- 加权无向图
- 加权有向图
- 有向无环图
图的存储
有3种数据结构可以存储图,如邻接矩阵、邻接表、链式前向星
1.邻接矩阵
用二维数组定义:int g[ N ][ N ];
无向图:g[i][j]=g[j][i];
有向图:g[i][j]!=g[j][i];
权值:g[i][j]存结点i到节点j的权值。
优点:适合稠密图,对边的增删改查操作简单。
缺点:
1. 存储复杂度高,可能会造成空间浪费
2. 一般情况下不能存重边
2.邻接表
struct edge//边
{
int from,to,w;//边:起点from、终点to、权值w
edge(int a,int b,int c)
{
from=a;
to=b;
w=c;
}
}
vector<edge> e[N];//e[i]:存第i个结点连接的所有边**
优点:适用于稀疏图,存储效率比较高,存储时间复杂度O(V+E).可以存重边。
缺点:编程比邻接矩阵麻烦、访问和修改慢。
3.链式前向星
//链式前向星
struct Edge
{
int to,next,w;//边:到to、下一个边next、权值w。起点存在head中
Edge(int a,int b,int c){to=a;next=b;w=c;}
} edge[N];
int head[N];//h[i]表示 结点i指向的第一条边的位置
int idx;//记录head的末尾位置
void init()//初始化
{
for(int i=0;i<N;i++)
{
head[i]=-1;//表示没有节点从i出发
}
}
void addEdge(int from,int to,int w)//添加节点和边
{
edge[idx].to=to;
edge[idx].w=w;
edge[idx].next=head[from];//将当前边插入到 节点from指向的集合中 。
head[from]=idx++;//修改from指向的位置。
}
优点:存储效率高
缺点:不方便做删除操作。