2021.11.14数据结构实验课作业——图的应用(最小生成树和最短路)
Posted 快乐·永恒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021.11.14数据结构实验课作业——图的应用(最小生成树和最短路)相关的知识,希望对你有一定的参考价值。
图的基本操作(必做题)
问题描述:在图的存储结构上实现以下算法:
① Prim和Kruskal算法;
② Dijkstra和Floyd算法;(Floyd算法选做)
③ 拓扑排序和关键路径算法。(关键路径算法选做)
输入输出:
输入图的顶点和边,输出最小生成树顶点和边、最短路径顶点序列、拓扑排序顶点序列、关键路径顶点序列。
点击查看代码Public.h
#pragma once
const int MaxVertex = 10; //图中最多顶点数
const int MaxEdge = 100; //图中最多边数
const int MaxValue = 10000; //图中最大边权
struct EdgeType { //定义边集数组的元素类型
int from, to, weight; //假设权值为整数
bool operator<(const EdgeType& x) const {
return weight < x.weight;
}
};
template<typename T>
struct VertexType { //定义点集的元素类型
T data;
int in_sum;
};
点击查看代码Prim.h
#pragma once
#include <iostream>
#include "Public.h"
using namespace std;
template<typename T>
class PGraph {
public:
PGraph(T a[], int n, int m, EdgeType e[]); //构造函数,建立具有n个顶点m条边的图
~PGraph() { } //析构函数
void Prim(int v);
private:
T vertex[MaxVertex]; //存放图中顶点的数组
int edge[MaxVertex][MaxVertex]; //存放图中边的数组
int vertexNum, edgeNum; //图的顶点数和边数
int MinEdge(int edge[], int n);
};
template<typename T>
PGraph<T>::PGraph(T a[], int n, int m, EdgeType e[]) {
vertexNum = n; edgeNum = m;
for (int i = 0; i < vertexNum; ++i) //存储顶点
vertex[i] = a[i];
for (int i = 0; i < vertexNum; i++) //初始化邻接矩阵
for (int j = 0; j < vertexNum; ++j)
if (i == j)
edge[i][j] = 0;
else
edge[i][j] = MaxValue;
for (int i = 0; i < edgeNum; ++i)
edge[e[i].from][e[i].to] = edge[e[i].to][e[i].from] = e[i].weight;
}
template<typename T>
void PGraph<T>::Prim(int v) {//从顶点v出发
int i, j, k;
int adjvex[MaxVertex], lowcost[MaxVertex];
for (i = 0; i < vertexNum; i++) {//初始化辅助数组
lowcost[i] = edge[v][i];
adjvex[i] = v;
}
lowcost[v] = 0; //将顶点v加入集合U
for (k = 1; k < vertexNum; k++) {//迭代n-1次
j = MinEdge(lowcost, vertexNum); //寻找最短边的邻接点j
cout << "(" << vertex[j] << ", " << vertex[adjvex[j]] << ")" << lowcost[j] << endl;
lowcost[j] = 0; //顶点j加入集合U
for (i = 0; i < vertexNum; i++) //调整辅助数组
if (edge[i][j] < lowcost[i]) {
lowcost[i] = edge[i][j];
adjvex[i] = j;
}
}
}
template<typename T>
int PGraph<T>::MinEdge(int edge[], int n) {
int index = 0, min = MaxValue;
for (int i = 0; i < n; i++)
if (edge[i] != 0 && edge[i] < min) {
min = edge[i];
index = i;
}
return index;
}
点击查看代码Kruskal.h
#pragma once
#include <iostream>
#include <algorithm>
#include "Public.h"
using namespace std;
template<typename T> //定义模板类
class KGraph {
public:
KGraph(T a[], int n, int m, EdgeType e[]); //构造函数,生成n个顶点m条边的连通图
~KGraph() { } //析构函数
void Kruskal(); //Kruskal算法求最小生成树
private:
int FindRoot(int parent[], int v); //求顶点v所在集合的根
T vertex[MaxVertex]; //存储顶点的一维数组
EdgeType edge[MaxEdge]; //存储边的边集数组
int parent[MaxVertex]; //双亲表示法存储并查集
int vertexNum, edgeNum;
};
template<typename T>
KGraph<T>::KGraph(T a[], int n, int m, EdgeType e[]) {
vertexNum = n; edgeNum = m;
for (int i = 0; i < vertexNum; ++i)
vertex[i] = a[i];
for (int i = 0; i < edgeNum; ++i)
edge[i] = e[i];
}
template<typename T>
void KGraph<T>::Kruskal() {
int num = 0, i, vex1, vex2;
for (i = 0; i < vertexNum; ++i)
parent[i] = -1; //初始化n个连通分量
std::sort(edge, edge + edgeNum);
for (num = 0, i = 0; num < vertexNum - 1; ++i) //依次考察最短边
{
vex1 = FindRoot(parent, edge[i].from);
vex2 = FindRoot(parent, edge[i].to);
if (vex1 != vex2) { //位于不同的集合
cout << "(" << vertex[edge[i].from] << ", " << vertex[edge[i].to] << ")" << edge[i].weight << endl;
parent[vex2] = vex1; //合并集合
num++;
}
}
}
template<typename T>
int KGraph<T>::FindRoot(int parent[], int v) {//求顶点v所在集合的根
int t = v;
while (parent[t] > -1) //求顶点t的双亲一直到根
t = parent[t];
return t;
}
点击查看代码Dijkstra.h
#pragma once
#include <iostream>
#include <string>
#include "Public.h"
using namespace std;
template<typename T>
class DGraph {
public:
DGraph(T a[], int n, int m, EdgeType e[]); //构造函数,建立具有n个顶点m条边的图
~DGraph() { } //析构函数
void Dijkstra(int v);
private:
T vertex[MaxVertex]; //存放图中顶点的数组
int edge[MaxVertex][MaxVertex]; //存放图中边的数组
int vertexNum, edgeNum; //图的顶点数和边数
int MinEdge(int edge[], int n); //求v点到其他所有顶点的最短路径
bool visited[MaxVertex]; //标记该节点是否已经求得最短路径
};
template<typename T>
DGraph<T>::DGraph(T a[], int n, int m, EdgeType e[]) {
vertexNum = n; edgeNum = m;
for (int i = 0; i < vertexNum; ++i)
visited[i] = false;
for (int i = 0; i < vertexNum; ++i) //存储顶点
vertex[i] = a[i];
for (int i = 0; i < vertexNum; i++) //初始化邻接矩阵
for (int j = 0; j < vertexNum; ++j)
if (i == j)
edge[i][j] = 0;
else
edge[i][j] = MaxValue;
for (int i = 0; i < edgeNum; ++i)
edge[e[i].from][e[i].to] = edge[e[i].to][e[i].from] = e[i].weight;
}
template<typename T>
void DGraph<T>::Dijkstra(int v) {//从v点出发
int i, k, num, dist[MaxVertex];
string path[MaxVertex];
visited[v] = true;
for (i = 0; i < vertexNum; ++i) { // 初始化数组dist和path
dist[i] = edge[v][i];
if (dist[i] != 100) {//假设100为边上权的最大值
path[i].push_back(vertex[v]);
path[i] = path[i] + ", ";
path[i].push_back(vertex[i]);
}
else path[i] = "";
}
for (num = 1; num < vertexNum; ++num) {
k = MinEdge(dist, vertexNum); //在dist数组中找到最小值并返回下标
cout << "到" << k << "点的最短路径为" << path[k] << "。 路径长度为" << dist[k] << endl;
visited[k] = true;
for (i = 0; i < vertexNum; ++i) //修改数组dist和path
if (dist[i] > dist[k] + edge[k][i]) {
dist[i] = dist[k] + edge[k][i];
path[i] = path[k] + ", ";
path[i].push_back(vertex[i]);
}
}
}
template<typename T>
int DGraph<T>::MinEdge(int edge[], int n) {
int index = 0, min = 100;
for (int i = 0; i < n; i++)
if (!visited[i] && edge[i] != 0 && edge[i] < min) {
min = edge[i];
index = i;
}
return index;
}
点击查看代码TopSort.h
#pragma once
#include "Public.h"
#include <iostream>
template<typename T>
class TGraph {
public:
TGraph(T a[], int n, int m, EdgeType e[]);
~TGraph() {};
void TopSort();
private:
VertexType<T> vertex[MaxVertex];//存放图中顶点的数组
int edge[MaxVertex][MaxVertex];//存放图中边的数组
int vertexNum, edgeNum;//图的顶点数和边数
};
template<typename T>
TGraph<T>::TGraph(T a[], int n, int m, EdgeType e[]) {
vertexNum = n; edgeNum = m;
for (int i = 0; i < vertexNum; ++i) //存储顶点
vertex[i].data = a[i], vertex[i].in_sum = 0;
for (int i = 0; i < vertexNum; i++) //初始化邻接矩阵
for (int j = 0; j < vertexNum; ++j)
if (i == j)
edge[i][j] = 0;
else
edge[i][j] = MaxValue;
for (int i = 0; i < edgeNum; ++i) {
edge[e[i].from][e[i].to] = e[i].weight;
++vertex[e[i].to].in_sum;
}
for (int i = 0; i < vertexNum; ++i)
cout << vertex[i].data << \' \' << vertex[i].in_sum << endl;
}
template<typename T>
void TGraph<T>::TopSort() {
int sta[MaxVertex], top = -1, x;
for (int i = 0; i < vertexNum; ++i)
if (vertex[i].in_sum == 0)
sta[++top] = i;
while (top != -1) {
x = sta[top--];
cout << vertex[x].data << \' \';
for(int i=0; i<vertexNum; ++i)
if (edge[x][i] != MaxValue) {
--vertex[i].in_sum;
if (vertex[i].in_sum == 0)
sta[++top] = i;
}
}
}
/*
5
A B C D E
5
0 1 10
1 2 20
1 3 30
2 4 40
3 4 50
*/
点击查看代码main.cpp
#include <iostream>
#include "Dijkstra.h"
#include "Kruskal.h"
#include "TopSort.h"
#include "Prim.h"
int main(void) {
char ch[100];
int n, m;
EdgeType e[100];
cout << "请输入顶点数: ";
cin >> n;
cout << "请输入顶点: " << endl;
for (int i = 0; i < n; ++i)
cin >> ch[i];
cout << "请输入边数: ";
cin >> m;
for (int i, j, w, k = 0; k < m; ++k) {
cout << "请输入边依附的两个顶点的编号,以及边上的权值:";
cin >> i >> j >> w;
e[k].from = i;
e[k].to = j;
e[k].weight = w;
}
cout << "Kruskal 算法结果为: " << endl;
KGraph<char> KG(ch, n, m, e);
KG.Kruskal();
cout << "Prim 算法结果为: " << endl;
PGraph<char> PG(ch, n, m, e);
PG.Prim(0);
cout << "请输入需要求最短路的源点编号";
int v;
cin >> v;
DGraph<char> DG(ch, n, m, e);
cout << v << "起点到其他点的最短路为:" << endl;
DG.Dijkstra(v);
TGraph<char> TG(ch, n, m, e);
cout << "拓扑排序结果为:";
TG.TopSort();
cin >> n;
return 0;
}
/*
6
A B C D E F
9
0 1 34
0 5 19
0 2 46
1 4 12
2 5 25
5 4 26
5 3 25
3 4 38
2 3 17
*/
以上是关于2021.11.14数据结构实验课作业——图的应用(最小生成树和最短路)的主要内容,如果未能解决你的问题,请参考以下文章