图的运用
1.最小生成树
最小生成树其实是最小权重生成树的简称。一个有n个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有n个结点,并且有保持图连通的最少的边。最小生成树可以用克鲁斯卡尔算法或普里姆算法求出。
最小生成树性质:设G=(V,E)是一个连通网络,U是顶点集V的一个非空真子集。若(u,v)是G中一条“一个端点在U中(例如:u∈U),另一个端点不在U中的边(例如:v∈V-U),且(u,v)具有最小权值,则一定存在G的一棵最小生成树包括此边(u,v)。
普里姆算法
算法步骤:
1)首先将初始顶点u加入U中,对其余的每一顶点,将closedge[j]均初始化到u的边信息。
2)循环n-1次,做出以下处理:
从各边closedge中选出最小边closedge[k],输出此边;
将k加入u中
更新剩余每组最小边信息closedge[j],对于U-V中的边,新增加了一条从k到j的边,如果新边的权值比closedge[j].lowcost小,则将closedge[j].lowcost更新为新边的权值。
算法:
struct {
VerTexType adjvex;//最小边在U中的顶点
ArcType lowcast;//最小边上的权值
} closedge[MVNum];
void MiniSpanTree_Prim(AMGraph G,VerTexType u) {
k=Locatevex(G,u);//k为U顶点的下标
for(j=0; j<G.vexnum; ++j) {//进行初始化
if(j!=k)
closedge[j]={u,G.zrc[k][j]};
}
closedge[k].lowcast=0;//初始U=u
for(i=1;i<G.vexnum;++i){
//选择n-1个顶点,生成n-1条边
k=Min(closedge);
//求出T的下一节点:第k个顶点,closedge[k]中存有当前最小边
u0=closedge[k].adjvex;
v0=G.vex[k];
cout<<u0<<v0;//输出当前最小边
closedge[k].lowcast=0;//第k个结点并入U
for(j=0;j<G.vexnum;++j){
if(G.arcs[k][j]<closedge[j].lowcast)//新顶点并入后重新选择最小边
closedge[j]={G.vexs[k],G.arcs[k][j]};
}
}
}
2.最短路径
用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。迪杰斯特拉算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。
迪杰斯特拉算法基本思想:
创建两个表,OPEN, CLOSE。
OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。
1. 访问路网中距离起始点最近且没有被检查过的点,把这个点放入OPEN组中等待检查。
2. 从OPEN表中找出距起始点最近的点,找出这个点的所有子节点,把这个点放到CLOSE表中。
3. 遍历考察这个点的子节点。求出这些子节点距起始点的距离值,放子节点到OPEN表中。
4. 重复第2和第3步,直到OPEN表为空,或找到目标点。
void ShortestPath_DIJ(int n) {
int count = 0; //count是已求出最短路径的顶点数目
visit[0] = 1;
prevetrix[0] = 0;
count++;
for (int i = 1; i < n; i++) { //初始化
dis[i] = graph[0][i];
prevetrix[i] = 0;
}
while (count < n) {
int min = INF, target_index;
for (int i = 1; i < n; i++) {
if (visit[i] == 0 && min > dis[i]) { //找到距离源点最短的顶点target_index
min = dis[i];
target_index = i;
}
}
visit[target_index] = 1;
count++;
for (int i = 1; i < n; i++) {
if (visit[i] == 0 && dis[target_index] +
graph[target_index][i] < dis[i]) { //更新
dis[i] = dis[target_index] + graph[target_index][i];
prevetrix[i] = target_index;
}
}
}
}
求每一对顶点之间的最短距离(弗洛伊德算法)
1.在主函数中创建一个矩阵,存储输入的两点间的距离。
2.在Floyd函数中,初始化记录最短距离的矩阵和记录中介点的矩阵。初始化之后将主函数的矩阵复制给记录最短距离的矩阵。
3.用三层循环不断更新最短距离。
void ShortestPath_Floyd(AMGraph G) {
for(i=0; i<G.vexnum; ++i) {//各对顶点之间初始已知路径及距离
for(j=0; j<G.vexnum; ++j) {
D[i][j]=G.arcs[i][j];
if(D[i][j]<MaxInt && i!=j)
Path[i][j]=i;
else
Path[i][j]=-1;
}
}
for(k=0; k<G.vexnum; ++k) {
for(i=0; i<G.vexnum; ++i) {
for(j=0; j<G.vexnum; ++j) {
if(D[i][k]+D[k][j]<D[i][j]) {//从i经k到j的一条路径更短
D[i][j]=D[i][k]+D[k][j];//更新D[i][j]
Path[i][j]=Path[k][j];//更改j的前驱为k
}
}
}
}
}