#pragma once
//图,采用邻接矩阵储存
#ifndef My_Head_H
#define My_Head_H
#include "G://code/c++/myhead.h"
#endif // !My_Head_H
constexpr auto MAX_VERTEX_NUM = 20;
//采用邻接矩阵储存
template<typename ElemType1,typename ElemType2>
class MGraph
{
public:
//是否为空
bool Is_Empty();
//用Kruskal算法构造最小生成树
void Mini_Span_Tree_Kreskal();
//用Prim算法构造最小生成数
void Mini_Span_Tree_Prim(ElemType1 vertex);
//有向网从某个顶点出发到其余各点的最短路径(Dijkstra)
void Shortest_Path_Dijkstra();
//有向网各对顶点之间的最短路径(Floyd)
void Shortest_Path_Floyd();
protected:
//图的种类。有向图=0;有向网=1;无向图=2;无向网=3
int kind;
//图的顶点个数
int vexNum;
ElemType1 verxs[MAX_VERTEX_NUM];//顶点的数据值数组;
int arcNum;//图的边数
ElemType2 arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
//邻接矩阵,对于图用1和0表示是否相邻,对于网表示两顶点之间的权值
};
template<typename ElemType1, typename ElemType2>
bool MGraph<ElemType1, ElemType2>::Is_Empty()
{
return !vexNum;
}
template<typename ElemType1, typename ElemType2>
void MGraph<ElemType1, ElemType2>::Mini_Span_Tree_Kreskal()
{
struct
{
int begin;//边的起始点
int end;//边的结束点
ElemType2 cost;//边的权值
}edges[MAX_VERTEX_NUM];//按权值从大到小记录每条边的信息数组
int Min_Shortest;
int set[MAX_VERTEX_NUM] = { 0 };//生成最小生成树的辅助数组,用以判断有无产生环路
//将数组edges元素边的权值置为无限大以初始化
for (int k = 0; k < arcNum; k++)
edge[k].cost = INFINITY;
//扫描邻接矩阵,把各边按权重从小到大排序;
for (int i = 0; i < vexNum; i++)
{
for (int j = 0; j < vexNum; j++)
{
if (arc[i][j] != INFINITY)
{
for (k = 0; k < arcNum; k++)
if (arcs[i][j] < edge[k].cost) break;
Min_Shortest = k;
//找到辅助数组已经输入的边数
for (; edges[k].cost != INFINITY; k++);
for (; k > Min_Shortest; k--)
{
edgex[k].begin = edges[k - 1].begin;
edgex[k].end = edges[k - 1].end;
edgex[k].cost = edges[k - 1].cost;
}
//输入当前边的信息
edgex[k].begin = i;
edgex[k].end = j;
edgex[k].cost = arc[i][j];
}
}
}
int begin_set, end_set;
for (k = 1; k < vexNum; k++)
{
begin_set = find(set, edges[k].begin);
end_set = find(set, edges[k].end);
if (begin_set != end_set)
{
//说明二者并不在一个子集中,将边k加入到最小生成树中
set[begin_set] = end_set;
cout << edges[k].begin << "--" << edges[k].cost << "-->"edges[k].end << endl;
}
}
}
template<typename ElemType1, typename ElemType2>
void MGraph<ElemType1, ElemType2>::Mini_Span_Tree_Prim(ElemType1 vertex)
{
if (Is_Empty) return;
int min, i, j, t;
int adjvex[MAX_VERTEX_NUM];//保存相关顶点下标
int lowcost[MAX_VERTEX_NUM];//保存顶点离最小生成树的距离
lowcost[0] = 0;//初始化第一个为0,即将第一个结点加入生成树
for (i = 1; i < vexNum; i++)
{
lowcost[i] = arcs[0][i];
adjvex[i] = 0;
}
for (i = 1; i < vexNum; i++)
{
min = 65535;
for (j = 1; j < vexNum; j++)
{
if (lowcost[j] != 0 && lowcost[j] < min)
{
min = lowcost[j];
t = j;
}
adjvex[t] = 1;//标记该点进入最小生成树
cout << "--" << lowcost[t] << "-->" << t;
}
lowcost[t] = 0;
for (j = 1; j < vexNum; j++)
{
if (arcs[t][j] < lowcost[j] && lowcost[j] != 0)
{
lowcost[j] = arcs[t][j];
adjvex[j] = t;
}
}
}
}
template<typename ElemType1, typename ElemType2>
void MGraph<ElemType1, ElemType2>::Shortest_Path_Dijkstra()
{
int order = 1;//预存放生成最短路径的顺序号
int k; //存放起始点的下标
ElemType1 begin_vertex; //存放起始点的权值
ElemType2 shortest[MAX_VERTEX_NUM];//储存起始点到每个顶点的最短距离;
int path[MAX_VERTEX_NUM] = { 0 };//储存起始点通向每个点最短路径的前一个结点;
bool final[MAX_VERTEX_NUM] = { 0 };//表示是否已经生成到该点的最短路径;
cin >> begin_vertex; //输入起始点(点的值而不是标号)
while (1)
{
for (k = 0; k < vexNum && verxs[k] != begin_vertex; k++);
//如果找不到那个点,需要重新输入
if (k == vexNum)
{
cout << "顶点" << begin_vertex << "不存在,需要重新输入" << endl;
cin >> begin_vertex;
}
break; //找到该顶点,k为其下标。退出输入循环;
}
//至此k表示起始结点的下标
shortest[k] = 0;
final[k] = true;
path[k] = k;
for (int i = 0; i < vexNum; i++)
{
//用邻接矩阵初始化最初的最短距离
shortest[i] = arc[k][i];
if (arc[k][i] != INFINITY) path[i]= k;
}
for (i = 1; i < vexNum; i++)
{
//找到还未生成最短路径的所有点中和起始点距离最近的点,记录在min_i里。
int min = INFINITY;
int min_i;
for (int j = 0; j < vexNum; j++)
{
if (!final[j] && shortest[j] < min)
{
min = shortest[j];
min_i = j;
}
}
final[min_i] = 1;
for (int j = 0; j < vexNum; j++)
{
if (!final[j] && min + arc[min_i][j] < shortest[j])
{
shortest[j] = min + arc[min_i][j];
path[j] = min_i;
}
}
}
for (int j = 0; j < vexNum; j++)
cout << "-->" << path[j];
}
template<typename ElemType1, typename ElemType2>
void MGraph<ElemType1, ElemType2>::Shortest_Path_Floyd()
{
int path[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
ElemType2 D[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int i, j, k;
for (i = 0; i < vexNum; i++)
{
for (j = 0; j < vexNum; j++)
{
D[i][j] = arcs[i][j];
path[i][j] = j;
}
}
for (i = 0; i < vexNum; i++)
{
for (j = 0; j < vexNum; j++)
{
for (k = 0; k < vexNum; k++)
{
if (D[j][k] > D[j][i] + D[i][k])
{
D[j][k] = D[j][i] + D[i][k];
p[j][k] = p[j][i];
}
}
}
}
}
int find(int set[], int f)
{
while (set[f] > 0)
f = set[f];
return f;
}
数据结构-图的c++实现(包括最小生成树和最短路径的计算
最新推荐文章于 2022-03-08 16:31:46 发布