在数据结构中,图的构造一般为2种:
1)邻接矩阵(稠密图) 二维数组:
无向图:对称(主对角线)
有向图:不对称
2) 邻接表(稀疏图) 一维数组链表:
无向图:一张邻接表
有向图:2张邻接表(出度表、入度表)
一般构造步骤(选择):
1)邻接矩阵 与 邻接表
2)有向图 与 无向图
3) 无权边 与 有权边
邻接矩阵:无向图、无权边
#include<iostream>
using namespace std;
#define N 100
struct Node
{
char data;
};
struct Graph
{
int vexnum;
int arcnum;
Node node[N]; // N个顶点信息
int matrix[N][N];
};
int Loc_vec(Graph G,char a)
{
for(int i=1;i<=G.vexnum;i++)
{
if(G.node[i].data == a)
{return i;
}
}
}
void Input(Graph &G)
{
cin>>G.vexnum>>G.arcnum;
for(int i=1;i<=G.vexnum;i++)
{
for(int j=1;j<=G.vexnum;j++)
{
G.matrix[i][j] = 0;
}
}
for(int i=1;i<=G.vexnum;i++)
{
cin>>G.node[i].data;
}
char a,b;
for(int i=1;i<=G.arcnum;i++)
{
cin>>a>>b;
int x = Loc_vec(G,a);
int y = Loc_vec(G,b);
G.matrix[x][y] = G.matrix[y][x] = 1;
}
}
void Output(Graph G)
{
for(int i=1;i<=G.vexnum;i++)
{
for(int j=1;j<=G.vexnum;j++)
{
if(G.matrix[i][j]==1)
{
cout<<G.node[i].data<<" "<<G.node[j].data<<endl;
G.matrix[j][i] = 0;
}
}
}
}
int main()
{
Graph G;
Input(G);
cout<<"Output:"<<endl;
Output(G);
return 0;
}
邻接表:无向图,有权边
// 邻接: adjoin
// AdjList
#include<iostream>
using namespace std;
#define N 100
struct Enode{ // 每个顶点的链表
int loc; // 在顶点AdjList[N]中的位置
struct Enode *next;
int weight;
};
struct Vnode{ // 一维顶点信息
char data;
Enode *first;
};
struct Graph{
int vexnum;
int arcnum;
Vnode AdjList[N];
};
int Loc_vex(Graph G,char a)
{
for(int i=1;i<=G.vexnum;i++)
{
if(G.AdjList[i].data == a)
{return i;
}
}
}
void Input(Graph &G)
{
cin>>G.vexnum>>G.arcnum;
for(int i=1;i<=G.vexnum;i++)
{
cin>>G.AdjList[i].data;
G.AdjList->first = NULL;
}
char a,b;
int w;
for(int i=1;i<=G.arcnum;i++)
{
cin>>a>>b>>w;
int x,y;
x = Loc_vex(G,a);
y = Loc_vex(G,b);
// a->b
Enode *p = new Enode;
p->loc = y;
p->weight = w;
p->next = NULL;
G.AdjList[x].first = p;
// b->a
Enode *q = new Enode;
q->loc = x;
q->weight = w;
q->next = NULL;
G.AdjList[y].first = q;
}
}
void Output(Graph &G)
{
for(int i=1;i<=G.vexnum;i++)
{
cout<<G.AdjList[i].data<<" ";
Enode *p;
p = G.AdjList[i].first;
while(p)
{
cout<<G.AdjList[p->loc].data<<" "<<p->weight<<endl;
p = p->next;
}
}
}
int main()
{
Graph G;
Input(G);
Output(G);
return 0;
}
图的基础是遍历: bfs,dfs
图的应用也有多种:
1.最小生成树(Prim,Kruskal):
一般为带权无向图,求任意2个点都连通时,最小的权值和。
例如:要在n个城市之间铺设光缆,主要目标是要使这 n 个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同,因此另一个目标是要使铺设光缆的总费用最低。
2.最短路径(dijkstra , Floyd):
dijkstra:某点到其余各点的最短路径。
Floyd:任意两点之间最短路径。
3.拓扑排序:
检测图中是否有环,也就是求某个点的前驱路径。若无环,则所有顶点都在它的拓扑有序序列中,即能完成拓扑排序
DAG:有向无环图
AOV网 (不能出现有向环):顶点表示活动,边表示先后关系的有向无环图
4.求关键路径:
AOE网:边表示活动,带权有向无环图
也需要用到拓扑排序