K短路径算法

本文介绍了K短路径算法,特别是Yen's算法的背景、简介和实例。Yen's算法用于非负权有向无环图,通过迭代和Dijkstra算法寻找最短路径。在给出的实例中,展示了如何找到从C到H的前三个最短路径。
摘要由CSDN通过智能技术生成

                                          K短路径算法

 

算法背景

K 最短路径问题是最短路径问题的扩展和变形。1959 年,霍夫曼(Hoffman) 和帕夫雷(Pavley)在论文中第一次提出k 最短路径问题。 k 最短路径问题通常包括两类:有限制的k 最短路问题和无限制的K 最短路问题。 前者要求最短路径集合不含有回路,而后者对所求得的最短路径集合无限制。

算法简介

Yen's算法是Yen 在1971 年提出的以其名字命名 的Yen 算法。Yen's算法采用了递推法中的偏离路径算法思想,适用于非负权边的有向无环图结构。

算法实例:

调用K条最短路径算法,源C,目的H,K为3。B为偏离路径集合。

1.通过Dijkstra算法计算得到最短路径A^1C-E-F-H,其中,花费为5,A[1] = C-E-F-H

2.将A[1]作为迭代路径,进行第一次迭代:

(1)以部分迭代路径(即A[1])C路径中,C点为起点,将C-E路径之间的权值设为无穷大,进行一次Dijkstra,得到路径A^2-1C-D-F-H,花费为8,将A^2-1路径加入B;

(2)以部分迭代路径(即A[1])C-E路径中,E为起点,将E-F路径之间的权值设为无穷大,进行一次Dijkstra,得到路径A^2-2C-E-G-H,花费为7,将A^2-2路径加入B;

(3)以部分迭代路径(即A[1])C-E-F路径中,F为起点,将F-H路径之间的权值设为无穷大,进行一次Dijkstra,得到路径A^2-3C-E-F-G-H,花费为8,将A^2-3路径加入B;

迭代完成,B集合中有三条路径:C-D-F-HC-E-G-HC-E-F-G-H;选出花费最小的偏离路径C-E-G-HA[2] = C-E-G-H,移出B集合。

3.将A[2]作为迭代路径,进行第二次迭代:

(1)以部分迭代路径(即A[2])C路径中,C点为起点,将C-E路径之间的权值设为无穷大,进行一次Dijkstra,得到路径A^3-1C-D-F-H但B集合已存在该路径,故不存在偏移路径;

(2)以部分迭代路径(即A[2])C-E路径中,E点为起点,将E-GE-F路径之间的权值设为无穷大 (注意,这里设置两条路径的权值原因是这两条路径分别存在于A[1]和A[2]中),进行一次Dijkstra,得到路径A^3-2C-E-D-F-H,花费为8,将A^3-2加入B;

(3)以部分迭代路径(即A[2])C-E-G路径中,G点为起点,将C-H路径之间的权值设为无穷大,不存在偏移路径。

迭代完成,B集合中有三条路径:C-D-F-HC-E-F-G-HC-E-D-F-H;由于三条路径花费均为8,则根据最小节点数进行判断,选出偏离路径C-D-F-HA[3] = C-D-F-H

此时,选出了三条最短路径,分别是:

 

 A[1] = C-E-F-H

A[2] = C-E-G-H

A[3] = C-D-F-H

 

 头文件

#ifndef _GRAPH_H
#define _GRAPH_H

#include<stdio.h>
#include<stdlib.h>
#include<vector>
#include<iostream>
#include<fstream>
#include<sstream>
#include<stack>
using namespace std;

#define MAXNODE 99
#define INFINITY 9999
#define K 10

typedef int VertexType;
typedef int EdgeType;

typedef struct node{
	VertexType adjnode;
	struct node* next;
	EdgeType weight;
}EdgeNode;

typedef struct vnode{
	VertexType vertex;
	EdgeNode* firstedge;
}VertexNode;

typedef struct MatrixGraph{
	VertexType vexs[MAXNODE + 1];							//顶点表
	EdgeType edges[MAXNODE + 1][MAXNODE + 1];		//邻接矩阵,可看作边表
}MGraph;

typedef struct Pathstruct{							//用于保存一条路径,里面有每一跳的点和该路径总距离
	VertexType node[MAXNODE + 1];
	EdgeType distance ;
	int hop;
}Path;


typedef VertexNode AdjList[MAXNODE + 1];



class Graph{
public:
	Graph(string filename);
	~Graph(){};
	void FindKpath();
	void PrintOut();
	void Dijkstra(VertexType);
	Path Graph::Dijkstra(VertexType,VertexType);
	void DijkstraAll();
	void PrintShortestPath(VertexType);
	void PrintShortestPathAll(void);
	void KShortestPath(VertexType);


private:
	MGraph mgraph;
//	AdjList adjlist;
	EdgeType **dist; 
	VertexType **pre;
	Path  **Kpath[K+1];              //存储路径,起点存在node[0].node[i]就是第i跳的点

	int e,n;			//n是节点数node,e是边数edge
};


#endif

源文件

#include "graph.h"

//邻接表方式构建图
Graph::Graph(string filename){
	int j,k,w;
	
	ifstream fin(filename,ios::in);
	fin>>n;
	fin>>e;

	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			mgraph.edges[i][j] = INFINITY;
		}
		mgraph.vexs[i] = i;
	}

	for(int i = 1;i <= e;i++){
		fin>>j;
		fin>>k;
		fin>>w;
		mgraph.edges[j][k] = w;
		mgraph.edges[k][j] = w;
	}
	
	dist = (EdgeType **)malloc(sizeof(EdgeType*) * n);
	pre = (VertexType **)malloc(sizeof(VertexType*) * n);
	for(int i = 1; i <= K; i++){
		Kpath[i] = (Path **)malloc(sizeof(Path) * n);
		for(int j = 1; j <= n; j++)
			Kpath[i][j] = (Path *)malloc(sizeof(Path) * n);
	}
	for( int i = 1; i <= n; i++){
		dist[i] = (EdgeType *)malloc(sizeof(EdgeType) * n);
		pre[i] = (VertexType *)malloc(sizeof(VertexType) *n);
	}
	
}


//求出V点的所有最短路径,结果保存在类的变量Kpath[1][v][i]里面,1表示第一短路径,v、i表示从v到i,
//Kpath结构里,node[i]表示第几跳的点,node[0]是自身,也就是v,另外保存了总跳数和总距离
void Graph::Dijkstra(VertexType v){
	bool s[MAXNODE];

	for(int i = 1; i <= n; i++){
		dist[v][i] = mgraph.edges[v][i];
		s[i] = 0;

		if(dist[v][i] == INFINITY)
			pre[v][i] = 0;
		else
			pre[v][i] = v;
	}

 
	s[v] = 1;
	dist[v][v] = 0;

	for( int i = 2; i <= n; i++){
		VertexType u = v;
		EdgeType tmp = INFINITY;

		for(int j = 1; j <= n; j++){
			if(!s[j] && dist[v][j] < tmp){
				tmp = dist[v][j];
				u = j;
			}
		}
		s[u] = 1;
		for(int j = 1; j <= n; j++){
			if(mgraph.edges[u][j] + dist[v][u] < dist[v][j]){
				dist[v][j] = mgraph.edges[u][j] + dist[v][u];
				pre[v][j] = u;
			}
		}
	}

	for(VertexType i = 1; i <= n; i++){
		int counthop = 0;
		EdgeType length = 0;
		VertexType j = i;
		while(pre[v][j] != 0){
			length += mgraph.edges[j][pre[v][j]];
			j = pre[v][j];
			counthop++;
		}

		Kpath[1][v][i].hop = counthop;
		Kpath[1][v][i].distance = length;
		VertexType m = i;
		while(counthop){//处理结果是路径node[1]即为第一跳,根据pre[][]把结果弄出来
			Kpath[1][v][i].node[counthop] = m;
			m = pre[v][m];
			counthop--;
		}
		Kpath[1][v][i].node[counthop] = v;
	}
}


//这个跟上面有很大重复,稍微改了下,接收两个点,返回两点之间的最短
  • 9
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haikuotiankongdong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值