最短路径算法集锦

/*

Name: 最短路径算法集锦

Copyright:

Author: 巧若拙

Date: 12/11/14 15:32

Description:

列举了深度优先搜索的递归和非递归算法,Dijkstra最短路径算法,

基于Bellman-Fort最短路径算法的改进型广度优先搜索算法,

Floyd-Warshall最短路径算法的原始版和变化版

本文是阅读《啊哈!算法》后的学习笔记,代码与教材中有些差异,若有错误请指正,谢谢!

测试数据:

5 7

0 3 2

0 4 9

4 2 1

4 1 3

2 1 1

3 4 2

3 1 8

*/

#include<stdio.h>

#include<stdlib.h>

#define MAX 20   //最大顶点数量

#define MAXLEN 99999999   //最长路径

int book[MAX] = {0}; //标记该城市是否已经在路径中

int map[MAX][MAX] = {0};//邻接矩阵存储两城市间路程

int min = MAXLEN;  //城市间最短距离

int sum = 0;

int DeepSearchWay_1(int n, int startPos, int endPos);//深度优先搜索最短路径驱动程序

void dfs(int n, int curPos, int endPos, int dis);//深度优先搜索最短路径子程序

int DeepSearchWay_2(int n, int startPos, int endPos);//深度优先搜索最短路径非递归算法

int Dijkstra(int n, int startPos, int endPos);//Dijkstra最短路径算法

int bfs(int n, int startPos, int endPos);//改进的广度优先搜索最短路径算法

int Floyd(int n, int startPos, int endPos);//Floyd-Warshall最短路径算法

int Floyd2(int n, int startPos, int endPos);//Floyd-Warshall最短路径算法(原始版)

int Bellman(int n, int startPos, int endPos);//Bellman-Fort最短路径算法

int main()

{

int i, j, m, n, a, b, c;

int startPos, endPos;

printf("请输入城市数量:");

scanf("%d", &n);

printf("\n请输入公路数量:");

scanf("%d", &m);

for (i=0; i<n; i++) //初始化顶点数据

{

for (j=0; j<n; j++)

{

map[i][j] = (i == j) ? 0 : MAXLEN;

}

}

printf("\n请按照a b c格式输入城市间的道路信息:\n");

for (i=0; i<m; i++)//读入城市间的道路信息

{

scanf("%d%d%d", &a,&b,&c);

map[a][b] = c;

}

while (1)

{

printf("请输入起点城市编号:");

scanf("%d", &startPos);

printf("请输入终点城市编号:");

scanf("%d", &endPos);

min = DeepSearchWay_1(n, startPos, endPos);

printf("深度优先搜索1: %d->%d = %d\n", startPos, endPos, min);

min = DeepSearchWay_2(n, startPos, endPos);

printf("深度优先搜索2:%d->%d = %d\n", startPos, endPos, min);

min = Dijkstra(n, startPos, endPos);

printf("Dijkstra最短路径算法:%d->%d = %d\n", startPos, endPos, min);

min = bfs(n, startPos, endPos);

printf("改进的广度优先搜索:%d->%d = %d\n", startPos, endPos, min);

min = Floyd(n, startPos, endPos);

printf("Floyd-Warshall最短路径算法:%d->%d = %d\n", startPos, endPos, min);

min = Floyd2(n, startPos, endPos);

printf("Floyd-Warshall最短路径算法2:%d->%d = %d\n", startPos, endPos, min);

min = Bellman(n, startPos, endPos);

printf("Bellman-Fort最短路径算法:%d->%d = %d\n", startPos, endPos, min);

}

return 0;

}

int DeepSearchWay_1(int n, int startPos, int endPos)//深度优先搜索最短路径驱动程序

{

int i;

for (i=0; i<n; i++)

book[i] = 0;

sum = 0;

min = MAXLEN;  //城市间最短距离

book[startPos] = 1;

dfs(n, startPos, endPos, 0);

printf("搜索次数为 %d\n", sum);

return min;

}

void dfs(int n, int curPos, int endPos, int dis)//深度优先搜索最短路径子程序

{

int i;

if (dis > min) //当前路程已大于最短路程,直接返回

return ;

if (curPos == endPos)

{

if (dis < min)

min = dis;

return ;

}

for (i=0; i<n; i++)

{

if (book[i] == 0 && map[curPos][i] != MAXLEN)

{

book[i] = 1;

dfs(n, i, endPos, dis+map[curPos][i]);

book[i] = 0;

}

sum++;

}

}

int DeepSearchWay_2(int n, int startPos, int endPos)//深度优先搜索最短路径非递归算法

{

int Vex[MAX] = {0};

int Stack[MAX] = {0};

int Dis[MAX] = {0};

int i, cur, top = 0;

int sum = 0;

for (i=0; i<n; i++)

book[i] = 0;

for (i=0; i<n; i++)

Dis[i] = map[startPos][i];

Stack[top] = startPos;

book[startPos] = 1;

while (top >= 0)

{

if (Vex[top] < n)

{

i = Vex[top];

cur = Stack[top];

if (book[i] == 0 && map[cur][i] != MAXLEN)

{

if (Dis[i] > Dis[cur] + map[cur][i]) //对各条边进行松弛

{

Dis[i] = Dis[cur] + map[cur][i];

}

if (i != endPos)

{

Stack[++top] = i;

book[i] = 1; //接入路径

Vex[top] = 0;

}

else

Vex[top]++;

}

else

{

Vex[top]++;

}

sum++;

}

else //退栈

{

book[Stack[top]] = 0; //离开路径

top--;

if (top >= 0) //转向下一条边

{

Vex[top]++;

}

}

}

printf("搜索次数为 %d\n", sum);

return Dis[endPos];

}

int Dijkstra(int n, int startPos, int endPos)//Dijkstra最短路径算法

{

int i, j, v, min;

int Dis[MAX] = {0};

int sum = 0;

for (i=0; i<n; i++)

book[i] = 0;

for (i=0; i<n; i++)

Dis[i] = map[startPos][i];

book[startPos] = 1;

for (j=1; j<n; j++)

{

min = MAXLEN;  //城市间最短距离

v = startPos;

for (i=0; i<n; i++) //寻找距离startPos最近的城市

{

if (book[i] == 0 && Dis[i] < min)

{

min = Dis[i];

v = i;

}

sum++;

}

if (v == endPos) //已经找到最短路径

break;

book[v] = 1;

for (i=0; i<n; i++) //对城市v的边进行松弛

{

if (map[v][i] != MAXLEN)

{

if (Dis[i] > Dis[v] + map[v][i])

Dis[i] = Dis[v] + map[v][i];

}

sum++;

}

}

printf("搜索次数为 %d\n", sum);

return Dis[endPos];

}

int bfs(int n, int startPos, int endPos)//改进的广度优先搜索最短路径算法

{

int i, k, front, rear;

int Dis[MAX] = {0};

int Queue[MAX] = {0};

int sum = 0;

for (i=0; i<n; i++)

book[i] = 0;

for (i=0; i<n; i++)

Dis[i] = MAXLEN;

Dis[startPos] = 0;

book[startPos] = 1;

front = rear = 0;

Queue[rear++] = startPos;

while (front != rear)

{

k = Queue[front];

for (i=0; i<n; i++) //遍历结点k的各条边

{

if (Dis[i] > Dis[k] + map[k][i])

{

Dis[i] = Dis[k] + map[k][i];

if (book[i] == 0)//入队列

{

Queue[rear] = i;

rear = (rear + 1) % MAX;

book[i] = 1;

}

}

sum++;

}

book[k] = 0;

front = (front + 1) % MAX;

}

printf("搜索次数为 %d\n", sum);

return Dis[endPos];

}

int Floyd(int n, int startPos, int endPos)//Floyd-Warshall最短路径算法

{

int i, j, flag;

int Dis[MAX] = {0};

int sum = 0;

for (i=0; i<n; i++)

Dis[i] = map[startPos][i];

flag = 1;

while (flag)

{

flag = 0;

for (i=0; i<n; i++)

{

for (j=0; j<n; j++)

{

if (Dis[i] > Dis[j] + map[j][i])

{

Dis[i] = Dis[j] + map[j][i];

flag = 1;

}

sum++;

}

}

}

printf("搜索次数为 %d\n", sum);

return Dis[endPos];

}

int Floyd2(int n, int startPos, int endPos)//Floyd-Warshall最短路径算法(原始版)

{

int i, j, k;

int Dis[MAX][MAX] = {0};

int sum = 0;

for (i=0; i<n; i++)

for (j=0; j<n; j++)

Dis[i][j] = map[i][j];

for (k=0; k <n; k++)

{

for (i=0; i<n; i++)

{

for (j=0; j<n; j++)

{

if (Dis[i][j] > Dis[i][k] + Dis[k][j])

{

Dis[i][j] = Dis[i][k] + Dis[k][j];

}

sum++;

}

}

}

printf("搜索次数为 %d\n", sum);

return Dis[startPos][endPos];

}

int Bellman(int n, int startPos, int endPos)//Bellman-Fort最短路径算法

{

int i, j, m = 0;

int Dis[MAX] = {0};

int u[MAX*MAX] = {0};

int v[MAX*MAX] = {0};

int w[MAX*MAX] = {0};

int sum = 0;

for (i=0; i<n; i++)

{

for (j=0; j<n; j++)

{

if (i != j && map[i][j] != MAXLEN)

{

u[m] = i;

v[m] = j;

w[m++] = map[i][j];

}

}

}

for (i=0; i<n; i++)

Dis[i] = map[startPos][i];

for (i=1; i<n; i++) //只需调整n-1次

{

for (j=0; j<m; j++)

{

if (Dis[v[j]] > Dis[u[j]] + w[j])

{

Dis[v[j]] = Dis[u[j]] + w[j];

}

sum++;

}

}

printf("搜索次数为 %d\n", sum);

return Dis[endPos];

}

时间: 2024-08-09 15:09:25

最短路径算法集锦的相关文章

最短路径算法专题1----弗洛伊德

由于最短路径算法我认为比较重要,所以分成几个专题来慢慢细化去磨它,不能一口气吃个胖子嘛. 首先在说算法之前,先说清楚什么叫做最短路径. 题目一般会给你一张图,然后告诉你很多地方,然后告诉你各个地方之间的路程有多远,要你求出,两点间的最短距离,注意,题目给出的两点间的距离未必是最短的,可能通过第三个点转换之后达到更短.实际其实也是这样的,有时候两个地方并没有直线的道路只有曲线的绕路. 算法的思路: 1.用二维数组列出所有的距离,达到不了的用最大距离表示,如9999999 2.循环数组上面的每一个点

图论之最短路径算法

简介: 求最短路径算法中最具代表性的是Dijkstra算法. Dijkstra算法的思想是基于贪心策略的. 概述其过程是通过设置顶点集合S并不断地做贪心选择来扩充集合. 贪心选择的标准是每次都选择从源节点到该节点的路径长度最短. 难点: 网络上博客中大多数人写的最短路径算法大多都是只能寻找到最短的一条路径. 但是很多时候可能存在并列最短的路径,需要找出所有同时最短的路径. 在这里我给大家分享一个时间复杂度大概是O(n2)的算法,求并列最短路径算法. 求出一条最短路径的算法步骤如下: 假设G={V

最短路径算法

最短路径-Dijkstra算法和Floyd算法 1.Dijkstra算法 1.1.定义概览Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边. 问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点

最短路径算法整理(二)

本文是最短路径算法整理的第二篇,想阅读第一篇的朋友能够点击下面链接: http://blog.csdn.net/hjd_love_zzt/article/details/26739593 这一篇博客继续以一些OJ上的题目为载体,整理一下最短路径算法.会陆续的更新... 1.HDU 2544 题目与分析:这道题抽象一下,还是:"求a到b的最短路径"..所须要的基本条件是:点数.边数.起点.终点 下面给出floyd.dijkstra.bellmanford三种最短路径算法关于这道题的解法:

最短路径算法学习总结

Dijkstra最短路径算法: dijkstra 算法的优点在于可以求出从一点到所有其他点的最短距离: input: 5 71 2 101 3 201 5 302 5 102 3 54 5 204 3 30 output: 0 10 15 40 20//这是求的在这颗树中,1到所有点的最短距离 1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int N=1100; 5 const int

无向图的最短路径算法JAVA实现(转)

一,问题描述 给出一个无向图,指定无向图中某个顶点作为源点.求出图中所有顶点到源点的最短路径. 无向图的最短路径其实是源点到该顶点的最少边的数目. 本文假设图的信息保存在文件中,通过读取文件来构造图.文件内容的格式参考这篇文章第一部分. 二,算法实现思路 无向图的最短路径实现相对于带权的有向图最短路径实现要简单得多. 源点的最短路径距离为0,从源点开始,采用广度优先的顺序,首先将与源点邻接的顶点的路径求出,然后再依次求解图中其他顶点的最短路径. 由于顶点的最短路径的求解顺序 是一个 广度优先的顺

最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)

一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine-->mine..... 那么,就存在这样一个问题:给定一个单词作为起始单词(相当于图的源点),给定另一个单词作为终点,求从起点单词经过的最少变换(每次变换只会变换一个字符),变成终点单词. 这个问题,其实就是最短路径问题. 由于最短路径问题中,求解源点到终点的最短路径与求解源点到图中所有顶点的最短路径复

几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较(转)

几大最短路径算法比较 几个最短路径算法的比较:Floyd        求多源.无负权边(此处错误?应该可以有负权边)的最短路.用矩阵记录图.时效性较差,时间复杂度O(V^3).       Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题. Floyd-Warshall算法的时间复杂度为O(N^3),空间复杂度为O(N^2). Floyd-Warshall的原理是动态规划:设Di,j

(最短路径算法整理)dijkstra、floyd、bellman-ford、spfa算法模板的整理与介绍

这一篇博客以一些OJ上的题目为载体.整理一下最短路径算法.会陆续的更新... 一.多源最短路算法--floyd算法 floyd算法主要用于求随意两点间的最短路径.也成最短最短路径问题. 核心代码: /** *floyd算法 */ void floyd() { int i, j, k; for (k = 1; k <= n; ++k) {//遍历全部的中间点 for (i = 1; i <= n; ++i) {//遍历全部的起点 for (j = 1; j <= n; ++j) {//遍历