一.问题分类
二.无权图单源最短路算法
dist[]数组记录的是个个顶点到源点的距离这个数组的下标表示顶点
源点到自己的距离是0,dist[s]=0
path[]数组记录的是这个顶点的前驱,可以同过这个数组找到源点到个个顶点的距离
代码如下
void Unweighted(MGraph Graph, Vertex S) {
Vertex V,W;
dist[S] = 0;//初始化源点到自己的距离
queue<Vertex>q;
q.push(S);//压栈
while(!q.empty()) {
/*弹栈*/
V = q.front();
q.pop();
for (W = 0; W < Graph->Nv; W++) {
/*点W到源点的距离没有被确定并且两个顶点有边,*/
if (dist[W] == -1 && IsEdge(Graph, V, W) ){
dist[W] = dist[V] + 1;/*更新距离*/
path[W] = V;//记录W的前驱
q.push(W);
}
}
}
}
dist[]和path[]都初始为-1
全部代码
#include<iostream>
#include<queue>
using namespace std;
#define INIFIN 65535/*表示没有边*/
#define MaxVertenNum 100/*最大顶点值*/
typedef int Vertex;/*顶点的下标用整形表示*/
typedef int WeightType;/*权重*/
int dist[MaxVertenNum], path[MaxVertenNum];
/* 边的定义*/
typedef struct ENode* PtrToENode;
struct ENode
{
Vertex V1, V2;/*有向图<v1,v2>*/
//WeightType Weight;/*权重*/
};
typedef PtrToENode Edge;
//图的定义
typedef struct GNode* PtrToGNode;
struct GNode {
int Nv;/*顶点个数*/
int Ne;/*边的个数*/
WeightType G[MaxVertenNum][MaxVertenNum];
};
typedef PtrToGNode MGraph;
MGraph CreateGraph(int VerNum) {
/*创建1个VN个顶点0条边的图*/
Vertex V, W;
MGraph Graph = new GNode();
Graph->Nv = VerNum;
Graph->Ne = 0;
for (V = 0; V < Graph->Nv; V++)
for (W = 0; W < Graph->Nv; W++)
Graph->G[V][W] = INIFIN;
return Graph;
}
//插入边
void InsertEdge(MGraph Graph, Edge E)
{
/* 插入边 <V1, V2> */
Graph->G[E->V1][E->V2] = 1;
/* 若是无向图,还要插入边<V2, V1> */
//Graph->G[E->V2][E->V1] = 1;
}
MGraph BuildGraph() {
Edge E;
MGraph Graph;
Vertex Nv;
cin >> Nv;/*顶点个数*/
Graph = CreateGraph(Nv);
cin >> Graph->Ne;/*输入边的个数*/
if (Graph->Ne != 0) {
for (int i = 0; i < Graph->Ne; i++) {
E = new ENode();
cin >> E->V1 >> E->V2;
InsertEdge(Graph, E);
}
}
return Graph;
}
bool IsEdge(MGraph G, Vertex v1, Vertex v2) {
return G->G[v1][v2] < INIFIN ? true : false;
}
void Unweighted(MGraph Graph, Vertex S) {
Vertex V,W;
dist[S] = 0;//初始化源点到自己的距离
queue<Vertex>q;
q.push(S);//压栈
while(!q.empty()) {
/*弹栈*/
V = q.front();
q.pop();
for (W = 0; W < Graph->Nv; W++) {
/*点W到源点的距离没有被确定并且两个顶点有边,*/
if (dist[W] == -1 && IsEdge(Graph, V, W) ){
dist[W] = dist[V] + 1;/*更新距离*/
path[W] = V;//记录W的前驱
q.push(W);
}
}
}
}
void FindDp(int V) {
if (V == -1)
return;
FindDp(path[V]);
cout << V << " ";
}
int main()
{
MGraph G = BuildGraph();
for (int i = 0; i < MaxVertenNum; i++) {
dist[i] = path[i] = -1;
}
Unweighted(G, 0);
cout << "请输入终点顶点:";
int n;
cin >> n;
cout << "源点到终点的路径:";
FindDp(n);
cout << endl;
system("pause");
return 0;
}
/*
7
12
0 1
0 3
1 3
1 4
2 0
2 5
3 2
3 4
3 5
3 6
4 6
6 5
*/
运行结果
三.有权图单源最短路算法
S集合存储的是的已经确定最短距离的顶点,起初集合只有一个顶点源点
若顶点V没有收录到集合,dist[V]表示源点到顶点V的距离,但这个距离不是真正的最短路径,当V顶点被收录到集合的时候,dist[V]才是最短距离
每次从dist[]中找到距离最短的顶点
当有顶点加入到集合中的时候,可能会影响dits[W]的值,及顶点的邻接点
代码如下
Vertex FindMinDist(MGraph Graph) {
/*返回未被收入顶点中的最小dist者*/
Vertex MinV, V;
int MinDist = INFINITY;
for (V = 0; V < Graph->Nv; V++) {
if (Visted[V] == false && dist[V] < MinDist) {
/*若V未被收录,且dist[V]更小*/
MinDist = dist[V];/*更新最小距离*/
MinV = V;/*更新最小顶点*/
}
}
if (MinDist < INFINITY)/*若找到最小dist*/
return MinV;/*返回对应的顶点下标*/
else return 0;/*若这样的顶点不存在,返回错误标记*/
}
bool Dijkstra(MGraph Graph, Vertex S) {
Vertex V, W;
/*初始化:此处默认邻接矩阵中不存在的边用INFINITY表示*/
for (V = 0; V < Graph->Nv; V++) {
dist[V] = Graph->G[S][V];//与S结点邻接把边值放到dist中
if (dist[V] < INFINITY)//有边记录它的前驱
path[V] = S; //记录V的前驱V的前驱是S
else
path[V] = -1;
Visted[V] = false;//全部顶点都没有收录
}
/*先将收起点收入集合*/
dist[S] = 0;
Visted[S] = true;//放到集合中
while (1) {
/*找到未被收入顶点中dist最小者*/
V = FindMinDist(Graph);
if (!V)/*如不存在*/
break;//算法结束
Visted[V] = true;//收录V
for (W = 0; W < Graph->Nv; W++)
if (Visted[W] == false && Graph->G[V][W] < INFINITY) {
if (Graph->G[V][W] < 0)//若有负边
return false;//
if (dist[V] + Graph->G[V][W] < dist[W]) {
dist[W] = dist[V] + Graph->G[V][W];
path[W] = V;//跟新S到W的路径
}
}
}
return true;
}
全部代码
#include<iostream>
using namespace std;
#define INFINITY 65535/*设为最大值*/
#define MaxVertexNum 100 /*最大顶点树设为100*/
typedef int Vertex; /*用顶点下标表示为整型*/
typedef int WeightType;/*边的权值设为整型*/
typedef char DataType;/*顶点存储的数据类型设为字符型*/
int Visted[MaxVertexNum];//集合等于false的都属于未被找的最短路径的结点
int dist[MaxVertexNum];//路径长度//
int path[MaxVertexNum];
/*边的定义*/
typedef struct ENode* PtrToENode;
struct ENode {
Vertex V1, V2;/*有向边<v1,v2>*/
WeightType Weight;/*权重 */
}; typedef PtrToENode Edge;
/*图的定义*/
typedef struct GNode* PtrToGNode;
struct GNode
{
int Nv;/*顶点个数*/
int Ne;/*边的个数*/
WeightType G[MaxVertexNum][MaxVertexNum];
};
typedef PtrToGNode MGraph;/*以邻接矩阵存储的图的类型*/
MGraph CreateGraph(int VertexNum) {
/*初始化一个有VN个顶点但没有边的图*/
Vertex V, W;
MGraph Graph;
Graph = new GNode();
Graph->Nv = VertexNum;
Graph->Ne = 0;
/*初始化邻接矩阵*/
for (V = 0; V < Graph->Nv; V++)
for (W = 0; W < Graph->Nv; W++)
Graph->G[V][W] = INFINITY;
return Graph;
}
void Insert(MGraph Graph, Edge E) {
Graph->G[E->V1][E->V2] = E->Weight;
}
bool IsEdge(MGraph Graph, Vertex V, Vertex W) {
return Graph->G[V][W] < INFINITY ? true : false;
}
/*邻接矩阵存储*/
Vertex FindMinDist(MGraph Graph) {
/*返回未被收入顶点中的最小dist者*/
Vertex MinV, V;
int MinDist = INFINITY;
for (V = 0; V < Graph->Nv; V++) {
if (Visted[V] == false && dist[V] < MinDist) {
/*若V未被收录,且dist[V]更小*/
MinDist = dist[V];/*更新最小距离*/
MinV = V;/*更新最小顶点*/
}
}
if (MinDist < INFINITY)/*若找到最小dist*/
return MinV;/*返回对应的顶点下标*/
else return 0;/*若这样的顶点不存在,返回错误标记*/
}
bool Dijkstra(MGraph Graph, Vertex S) {
Vertex V, W;
/*初始化:此处默认邻接矩阵中不存在的边用INFINITY表示*/
for (V = 0; V < Graph->Nv; V++) {
dist[V] = Graph->G[S][V];//与S结点邻接把边值放到dist中
if (dist[V] < INFINITY)//有边记录它的前驱
path[V] = S; //记录V的前驱V的前驱是S
else
path[V] = -1;
Visted[V] = false;//全部顶点都没有收录
}
/*先将收起点收入集合*/
dist[S] = 0;
Visted[S] = true;//放到集合中
while (1) {
/*找到未被收入顶点中dist最小者*/
V = FindMinDist(Graph);
if (!V)/*如不存在*/
break;//算法结束
Visted[V] = true;//收录V
for (W = 0; W < Graph->Nv; W++)
if (Visted[W] == false && Graph->G[V][W] < INFINITY) {
if (Graph->G[V][W] < 0)//若有负边
return false;//
if (dist[V] + Graph->G[V][W] < dist[W]) {
dist[W] = dist[V] + Graph->G[V][W];
path[W] = V;//跟新S到W的路径
}
}
}
return true;
}
void FindDp(int V) {
if (V == -1)
return;
FindDp(path[V]);
cout << V << endl;
}
int main()
{
MGraph Graph = CreateGraph(7);
Graph->Ne = 12;
Vertex a[12] = { 0,0,1,1,2,2,3,3,3,3,4,6 };
Vertex b[12] = { 1,3,3,4,0,5,2,4,5,6,6,5 };
WeightType w[12] = { 2,1,3,10,4,5,2,2,8,4,6,1 };
/* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */
for (int i = 0; i < Graph->Ne; i++) {
Edge E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */
E->V1 = a[i]; E->V2 = b[i]; E->Weight = w[i];
/* 注意:如果权重不是整型,Weight的读入格式要改 */
Insert(Graph, E);
}
for (int i = 0; i < MaxVertexNum; i++) { Visted[i] = false; dist[i] = INFINITY; path[i] = -1; }
Dijkstra(Graph, 0);
int n;
cin >> n;
FindDp(n);
return 0;
}
运行结果
四.多源最短路算法
D^k[i][j]表示i到j经过k的最小长度
依次将每个点作为中间点去做更新
k=V-1是D[i][j]将最小路径更新完成
bool Floyd(MGraph Graph) {
for(int i=0;i<Graph->Nv;i++)
for (int j = 0; j < Graph->Nv; j++) {
D[i][j] = Graph->G[i][j];
path[i][j] = -1;
}
/*k表示中间点*/
for(int k=0;k<Graph->Nv;k++)
for (int i = 0; i < Graph->Nv; i++)
for (int j = 0; j < Graph->Nv; j++)
if (D[i][k] + D[k][j] < D[i][j]) {
D[i][j] = D[i][k] + D[k][j];
if (i == j && D[i][j] < 0)/*若出现负边无法解决*/
return false;
path[i][j] = k;
}
return true;
}
全部代码
#include<iostream>
using namespace std;
#define MaxvertexNum 100/*最大顶点值*/
#define INF 65535/*无穷大表示没有边直接相连*/
typedef int Vertex;/*顶点下标*/
typedef int WeightType;/*权重*/
WeightType D[MaxvertexNum][MaxvertexNum];/*D[i][j],顶点i到顶点j的最短距离*/
Vertex path[MaxvertexNum][MaxvertexNum];/*记录路径*/
/*边的定义*/
typedef struct ENode* PtrToENode;
struct ENode
{
Vertex V1, V2;
WeightType Weigtht;
};
typedef PtrToENode Edge;
/*图的定义*/
typedef struct GNode* PtrToGNode;
struct GNode {
int Nv;/*顶点个数*/
int Ne; /*边的个数*/
WeightType G[MaxvertexNum][MaxvertexNum];
};
typedef PtrToGNode MGraph;
MGraph CreateGraph(int Vertexnum) {
MGraph G = new GNode();
G->Nv = Vertexnum;
G->Ne = 0;
for (int i = 0; i < G->Nv; i++)
for (int j = 0; j < G->Nv; j++)
G->G[i][j] = INF;
return G;
}
void InsertEdeg(MGraph Graph, Edge E) {
Graph->G[E->V1][E->V2] = E->Weigtht;
Graph->G[E->V2][E->V1] = E->Weigtht;
}
bool Floyd(MGraph Graph) {
for(int i=0;i<Graph->Nv;i++)
for (int j = 0; j < Graph->Nv; j++) {
D[i][j] = Graph->G[i][j];
path[i][j] = -1;
}
/*k表示中间点*/
for(int k=0;k<Graph->Nv;k++)
for (int i = 0; i < Graph->Nv; i++)
for (int j = 0; j < Graph->Nv; j++)
if (D[i][k] + D[k][j] < D[i][j]) {
D[i][j] = D[i][k] + D[k][j];
if (i == j && D[i][j] < 0)/*若出现负边无法解决*/
return false;
path[i][j] = k;
}
return true;
}
//void FindDp(int i, int j) {
// if (path[i][j] == -1)
// return;
// FindDp(i, path[i][j]);
// cout << j;
//}
MGraph BuildGraph() {
Edge E;
MGraph Graph;
Vertex Nv;
cin >> Nv;/*顶点个数*/
Graph = CreateGraph(Nv);
cin >> Graph->Ne;/*输入边的个数*/
if (Graph->Ne != 0) {
for (int i = 0; i < Graph->Ne; i++) {
E = new ENode();
cin >> E->V1 >> E->V2>>E->Weigtht;
E->V1--;
E->V2--;
InsertEdeg(Graph, E);
}
}
return Graph;
}
int main()
{
MGraph Graph = BuildGraph();
Floyd(Graph);
int i,j;
// cin >> i>>j;
// FindDp(i,j);
return 0;
}
怎么样打印两点之间的路径还没有写好