实现在一张图中寻找K条最短路径(较短路径)。

代码测试过程中学习到的Python基础知识:

1、Python字符串的截取操作:

str[0:3] #截取第0位到第2位的字符

str[:] #截取字符串的全部字符

str[6:] #截取第七个字符到结尾

str[:-3] #截取从头开始到倒数第三个字符之前

str[2] #截取第三个字符

str[-1] #截取倒数第一个字符

str[::-1] #创造一个与原字符串顺序相反的字符串

str[-3:-1] #截取倒数第三位与倒数第一位之前的字符

str[-3:] #截取倒数第三位到结尾

str[:-5:-3] #逆序截取

2、Python获取字典中的元素:

dict.get(x)如果读取不存在的值,会返回默认值,比如None。

dict[x]如果读取不存在的值,就会运行报错,比如KeyError'x'。

可以使用print在程序中详细查看。

3、Dijkstra算法可以通过改进,变为K-最短路径算法。(参考网上实现)

4、对最后输出字符串的每三个字符进行逆序操作。(代码改进)

5、分析路径字符串,检测重复的点以去掉回路。(代码改进)

具体实现代码为(参考网上源码)

import heapq
import sysclass Graph:def __init__(self):self.vertices = {}def add_vertex(self, name, edges):self.vertices[name] = edgesdef get_shortest_path(self, startpoint, endpoint):# distances使用字典的方式保存每一个顶点到startpoint点的距离distances = {}# 从startpoint到某点的最优路径的前一个结点# eg:startpoint->B->D->E,则previous[E]=D,previous[D]=B,等等previous = {}# 用来保存图中所有顶点的到startpoint点的距离的优先队列# 这个距离不一定是最短距离nodes = []# Dikstra算法 数据初始化for vertex in self.vertices:if vertex == startpoint:# 将startpoint点的距离初始化为0distances[vertex] = 0heapq.heappush(nodes, [0, vertex])elif vertex in self.vertices[startpoint]:# 把与startpoint点相连的结点距离startpoint点的距离初始化为对应的弧长/路权distances[vertex] = self.vertices[startpoint][vertex]heapq.heappush(nodes, [self.vertices[startpoint][vertex], vertex])previous[vertex] = startpointelse:# 把与startpoint点不直接连接的结点距离startpoint的距离初始化为sys.maxsizedistances[vertex] = sys.maxsizeheapq.heappush(nodes, [sys.maxsize, vertex])previous[vertex] = Nonewhile nodes:# 取出队列中最小距离的结点smallest = heapq.heappop(nodes)[1]if smallest == endpoint:shortest_path = []lenPath = distances[smallest]temp = smallestwhile temp != startpoint:shortest_path.append(temp)temp = previous[temp]# 将startpoint点也加入到shortest_path中shortest_path.append(temp)if distances[smallest] == sys.maxsize:# 所有点不可达break# 遍历与smallest相连的结点,更新其与结点的距离、前继节点for neighbor in self.vertices[smallest]:dis = distances[smallest] + self.vertices[smallest][neighbor]if dis < distances[neighbor]:distances[neighbor] = dis# 更新与smallest相连的结点的前继节点previous[neighbor] = smallestfor node in nodes:if node[1] == neighbor:# 更新与smallest相连的结点到startpoint的距离node[0] = disbreakheapq.heapify(nodes)return distances, shortest_path, lenPathdef getMinDistancesIncrement(self, inputList):inputList.sort()lenList = [v[0] for v in inputList]minValue = min(lenList)minValue_index = lenList.index(minValue)minPath = [v[1] for v in inputList][minValue_index]return minValue, minPath, minValue_index# def deleteCirclesWithEndpoint(self,inputList, endpoint):#   '''#    该函数主要是删除类似于这样的例子: endpoint->...->endpoint-->...#     '''#     pathsList = [v[1] for v in inputList]#     for index, path in enumerate(pathsList):#       if len(path) > 1 and path[-1] == endpoint:#            inputList.pop(index)#   return inputListdef k_shortest_paths(self,start, finish, k = 3):''':param start: 起始点:param finish: 终点:param k: 给出需要求的最短路数:return: 返回K最短路和最短路长度该算法重复计算了最短路,调用get_shortest_path()方法只是用到了起始点到其他所有点的最短距离和最短路长度'''distances, _, shortestPathLen = self.get_shortest_path(start, finish)num_shortest_path = 0paths = dict()distancesIncrementList = [[0, finish]]while num_shortest_path < k:path = []#distancesIncrementList = self.deleteCirclesWithEndpoint(distancesIncrementList,finish)minValue, minPath, minIndex = self.getMinDistancesIncrement(distancesIncrementList)#print('m:'+minPath)smallest_vertex = minPath[-3:]#print('v:'+smallest_vertex)distancesIncrementList.pop(minIndex)if smallest_vertex == start:path.append(minPath[::-1])num_shortest_path += 1# type(path) -> list,不能作为字典的keypaths[path[0]] = minValue + shortestPathLen#print(paths)# 字典采用{path ; pathlen}这样的键值对,不能使用{pathlen:path}# 因为key是唯一的,所以在此相同长度的path只能保存一个,后来的会覆盖前面的# paths[minValue + shortestPathLen] = pathcontinuefor neighbor in self.vertices[smallest_vertex]:incrementValue = minPathincrement = 0if neighbor == finish:# 和函数deleteCirclesWithEndpoint()作用一样continueif distances[smallest_vertex] == (distances[neighbor] + self.vertices[smallest_vertex][neighbor]):increment = minValueelif distances[smallest_vertex] < (distances[neighbor] + self.vertices[smallest_vertex][neighbor]):increment = minValue + distances[neighbor] + self.vertices[smallest_vertex][neighbor] - distances[smallest_vertex]elif distances[neighbor] == (distances[smallest_vertex] + self.vertices[smallest_vertex][neighbor]):increment = minValue + 2 * self.vertices[smallest_vertex][neighbor]distancesIncrementList.append([increment, incrementValue + neighbor])return pathsif __name__ == '__main__':g = Graph() #这是图的存储g.add_vertex('a01', {'a02': 11.5, 'a70': 1.8, 'a74': 0.9})g.add_vertex('a02', {'a03': 3.6, 'a01': 11.5, 'a44': 6.5})g.add_vertex('a03', {'a02': 3.6, 'a04': 4.9, 'a14': 7.3, 'a15': 6.6, 'a58': 2.3})g.add_vertex('a04', {'a03': 4.9, 'a05': 6.3, 'a59': 1.1, 'a43': 2.1})g.add_vertex('a05', {'a04': 6.3, 'a06': 1.9, 'a17': 0.9, 'a27': 1.3})g.add_vertex('a06', {'a05': 1.9, 'a07': 3.1, 'a18': 1.2})g.add_vertex('a07', {'a06': 3.1, 'a08': 0.9, 'a19': 1.7, 'a34': 4.8})g.add_vertex('a08', {'a09': 3.3, 'a20': 1.9, 'a07': 0.9, 'a37': 5.7})g.add_vertex('a09', {'a10': 5.1, 'a84': 0.6, 'a08': 3.3, 'a87': 2})g.add_vertex('a10', {'a11': 5, 'a22': 0.8, 'a09': 5.1, 'a21': 3.2})g.add_vertex('a11', {'a12': 0.7, 'a10': 5, 'a22': 4.4})g.add_vertex('a12', {'a11': 0.7, 'a30': 6.6})g.add_vertex('a13', {'a14': 5.8, 'a81': 4, 'a45': 6})g.add_vertex('a14', {'a15': 0.8, 'a13': 5.8, 'a81': 8.2, 'a03': 7.3})g.add_vertex('a15', {'a55': 5.7, 'a81': 8.7, 'a14': 0.8, 'a03': 6.6})g.add_vertex('a16', {'a17': 2.4, 'a51': 3.9, 'a61': 1.9, 'a82': 3.1})g.add_vertex('a17', {'a18': 2.1, 'a28': 4.9, 'a16': 2.4, 'a05': 0.9})g.add_vertex('a18', {'a19': 2.5, 'a49': 3.9, 'a17': 2.1, 'a06': 1.2})g.add_vertex('a19', {'a20': 1, 'a36': 2.2, 'a48': 3.4, 'a18': 2.5, 'a07': 1.7})g.add_vertex('a20', {'a21': 4.1, 'a35': 1, 'a84': 4.2, 'a19': 1, 'a08': 1.9, 'a27': 6})g.add_vertex('a21', {'a10': 3.2, 'a20': 4.1, 'a84': 1.4})g.add_vertex('a22', {'a11': 4.4, 'a10': 0.8, 'a85': 4.8})g.add_vertex('a23', {'a24': 7.2, 'a31': 0.3, 'a80': 7.8,'a79': 2.4})g.add_vertex('a24', {'a25': 0.7, 'a32': 0.4, 'a23': 7.2})g.add_vertex('a25', {'a26': 1.3, 'a33': 0.5, 'a24': 0.7, 'a42': 8.3})g.add_vertex('a26', {'a27': 2.9, 'a34': 1.1, 'a83': 2.8, 'a25': 1.3})g.add_vertex('a27', {'a05': 1.3, 'a20': 6, 'a26': 2.9, 'a82': 2.1})g.add_vertex('a28', {'a29': 7.3, 'a17': 4.9, 'a36': 0.3})g.add_vertex('a29', {'a30': 1, 'a28': 7.3, 'a46': 6.6, 'a41': 2.1})g.add_vertex('a30', {'a12': 6.6, 'a29': 1})g.add_vertex('a31', {'a32': 8.1, 'a23': 0.3})g.add_vertex('a32', {'a33': 0.9, 'a37': 3.3, 'a24': 0.4, 'a31': 8.1})g.add_vertex('a33', {'a34': 0.8, 'a39': 3.9, 'a25': 0.5, 'a32': 0.9})g.add_vertex('a34', {'a07': 4.8, 'a26': 1.1, 'a33': 0.8})g.add_vertex('a35', {'a36': 0.6, 'a46': 1, 'a20': 1})g.add_vertex('a36', {'a40': 0.9, 'a28': 0.3, 'a19': 2.2, 'a35': 0.6})g.add_vertex('a37', {'a08': 5.7, 'a38': 0.6, 'a32': 3.3})g.add_vertex('a38', {'a39': 0.9, 'a37': 0.6})g.add_vertex('a39', {'a86': 2.9, 'a88': 1, 'a38': 0.9, 'a33': 3.9})g.add_vertex('a40', {'a46': 0.6, 'a41': 5.1, 'a36': 0.9, 'a47': 2.3})g.add_vertex('a41', {'a29': 2.1, 'a40': 5.1, 'a68': 8})g.add_vertex('a42', {'a82': 4.8, 'a25': 8.3, 'a43': 0.8, 'a78': 3.9})g.add_vertex('a43', {'a04': 2.1, 'a42': 0.8, 'a44':1 })g.add_vertex('a44', {'a43': 1, 'a59': 2.3, 'a02': 6.5, 'a79': 10.2})g.add_vertex('a45', {'a71': 3.3, 'a13': 6, 'a70': 5.9})g.add_vertex('a46', {'a29': 6.6, 'a35': 1, 'a40': 0.6})g.add_vertex('a47', {'a40': 2.3, 'a68': 8.5, 'a48': 1.3})g.add_vertex('a48', {'a47': 1.3, 'a67': 8.3, 'a19': 3.4, 'a49': 2.8})g.add_vertex('a49', {'a48': 2.8, 'a18': 3.9, 'a50': 2.7})g.add_vertex('a50', {'a49': 2.7, 'a53': 3.6, 'a51': 1.8})g.add_vertex('a51', {'a50': 1.8, 'a52': 0.7, 'a16': 3.9})g.add_vertex('a52', {'a51': 0.7, 'a53': 3.1, 'a63': 6.2})g.add_vertex('a53', {'a54': 0.7, 'a50': 3.6, 'a52': 3.1})g.add_vertex('a54', {'a66': 2.2, 'a53': 0.7, 'a65': 4.6})g.add_vertex('a55', {'a56': 1.5, 'a63': 3.5, 'a15': 5.7})g.add_vertex('a56', {'a60': 3, 'a62': 1.8, 'a55': 1.5, 'a57': 2})g.add_vertex('a57', {'a56': 2, 'a58': 1.9})g.add_vertex('a58', {'a59': 2.3, 'a57': 1.9, 'a71': 10.7, 'a03': 2.3})g.add_vertex('a59', {'a04': 1.1, 'a60': 3.6, 'a58': 2.3, 'a44': 2.3})g.add_vertex('a60', {'a61': 0.7, 'a56': 3, 'a59': 3.6})g.add_vertex('a61', {'a16': 1.9, 'a62': 3.6, 'a60': 0.7})g.add_vertex('a62', {'a63': 2.4, 'a56': 1.8, 'a61': 3.6})g.add_vertex('a63', {'a64': 3.4, 'a52': 6.2, 'a55': 3.5, 'a62': 2.4, 'a73': 11.7})g.add_vertex('a64', {'a65': 3.5, 'a69': 6.2, 'a63': 3.4})g.add_vertex('a65', {'a54': 4.6, 'a64': 3.5})g.add_vertex('a66', {'a67': 1.9, 'a54': 2.2, 'a69': 9})g.add_vertex('a67', {'a68': 2.5, 'a48': 8.3, 'a66': 1.9})g.add_vertex('a68', {'a41': 8, 'a47': 8.5, 'a67': 2.5})g.add_vertex('a69', {'a66': 9, 'a64': 6.2, 'a73': 6.8})g.add_vertex('a70', {'a45': 5.9, 'a01': 1.8})g.add_vertex('a71', {'a58': 10.7, 'a45': 3.3})g.add_vertex('a72', {'a73': 3.8, 'a81': 3.3})g.add_vertex('a73', {'a63': 11.7, 'a69': 6.8, 'a72': 3.8})g.add_vertex('a74', {'a75': 9.8, 'a78': 14.4, 'a01': 0.9})g.add_vertex('a75', {'a78': 11.5, 'a76': 9.7, 'a74': 9.8})g.add_vertex('a76', {'a77': 5.6, 'a80': 4.3, 'a75': 9.7})g.add_vertex('a77', {'a78': 8.3, 'a79': 6.3, 'a76': 5.6})g.add_vertex('a78', {'a42': 3.9, 'a74': 14.4, 'a75': 11.5, 'a77': 8.3})g.add_vertex('a79', {'a23': 2.4, 'a44': 10.2, 'a77': 6.3})g.add_vertex('a80', {'a23': 7.8, 'a76': 4.3})g.add_vertex('a81', {'a72': 3.3, 'a14': 8.2, 'a13': 4, 'a15': 8.7})g.add_vertex('a82', {'a27': 2.1, 'a16': 3.1, 'a42': 4.8, 'a83': 2.5})g.add_vertex('a83', {'a82': 2.5, 'a26':2.8})g.add_vertex('a84', {'a21': 1.4, 'a85': 5.1, 'a09': 0.6, 'a20': 4.2})g.add_vertex('a85', {'a22': 4.8, 'a84': 5.1, 'a90': 4.1})g.add_vertex('a86', {'a89': 2.6, 'a87': 2.6, 'a39': 2.9})g.add_vertex('a87', {'a09': 2, 'a90': 4.8, 'a86': 2.6})g.add_vertex('a88', {'a89': 3.3, 'a39': 1})g.add_vertex('a89', {'a90': 3.7, 'a86': 2.6, 'a88': 3.3})g.add_vertex('a90', {'a85': 4.1, 'a87': 4.8, 'a89': 3.7})start = 'a01'end = 'a90'k = 250 #这里是K值distances, shortestPath, shortestPathLen = g.get_shortest_path(start, end)#print('{}->{}的最短路径是:{},最短路径为:{}'.format(start, end, shortestPath, shortestPathLen))paths = g.k_shortest_paths(start, end, k)#print(paths)print('\n求得的 {}-->{} 的 {}-最短路 分别是:'.format(start, end, k))index = 1for path, length in paths.items():#每3个逆序i = 0j = 2realPath = ""while j <= len(path):temp1 = path[i:j+1]#print(temp1[::-1])realPath += temp1[::-1]i += 3j += 3#每3个检测重复k1 = 0k2 = 3flag = 0;while k1 <= len(realPath)-3:temp2 = realPath[k1:k1+3] #哨兵#print("2:"+temp2)while k2 <= len(realPath)-3:temp3 = realPath[k2:k2+3]#print("3:"+temp3)if temp2 == temp3:flag = 1breakk2 += 3k1 += 3k2  = k1 + 3#输出不重复的if flag==0:print('{}:{} 最短路长度:{}'.format(index, realPath, length))index += 1

参考文章:

https://blog.csdn.net/sxt1001/article/details/80956564

https://blog.csdn.net/qingzhuyuxian/article/details/79882088

Python算法实现 -- K最短路径算法相关推荐

  1. k均值算法 二分k均值算法_如何获得K均值算法面试问题

    k均值算法 二分k均值算法 数据科学访谈 (Data Science Interviews) KMeans is one of the most common and important cluste ...

  2. k均值算法 二分k均值算法_使用K均值对加勒比珊瑚礁进行分类

    k均值算法 二分k均值算法 Have you ever seen a Caribbean reef? Well if you haven't, prepare yourself. 您见过加勒比礁吗? ...

  3. 【JavaScript算法实践】最短路径算法

    目录 前言 一.Dijkstra算法 算法实现 二.Floyd-Warshall 算法 算法实现 前言 最短路问题是图问题中的经典问题,这类问题在生活中非常常见,我们(特别是生活在大城市的人)出门在外 ...

  4. KNN算法(K临近算法)及使用KNN算法实现手写数字0-9识别

    首先感谢博主倔强的小彬雅,本文使用的素材及部分代码来源其博文机器学习入门-用KNN实现手写数字图片识别(包含自己图片转化),需要下载素材的可以到其博文最后进行下载. 关于KNN算法 knn算法也叫K临 ...

  5. 数据挖掘--“聚类”详解、K-means、K-平均值算法、K均值算法

    一. 什么是聚类 二. 聚类步骤 三. 聚类算法有哪些 1 层次聚类算法 2 划分聚类算法 3 基于密度的聚类算法 4 基于网格的聚类算法 5 基于模型的聚类算法 一. 什么是聚类? 物以类聚,人以群 ...

  6. 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)

    带权图分为有向和无向,无向图的最短路径又叫做最小生成树,有prime算法和kruskal算法:有向图的最短路径算法有dijkstra算法和floyd算法. 生成树的概念:联通图G的一个子图如果是一棵包 ...

  7. 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)

    带权图分为有向和无向,无向图的最短路径又叫做最小生成树,有prime算法和kruskal算法:有向图的最短路径算法有dijkstra算法和floyd算法. 生成树的概念:联通图G的一个子图如果是一棵包 ...

  8. 机器学习算法总结--K均值算法

    参考自: <机器学习> 机器学习&数据挖掘笔记_16(常见面试之机器学习算法思想简单梳理) K-Means Clustering 斯坦福大学公开课 :机器学习课程 简介 K-均值是 ...

  9. KNN算法(K最近邻算法)详解

    K 最近邻的核心数学知识是距离的计算和权重的计算.我们把需要预测的点作为中心点,然后计算其周围一定半径内的已知点距其的距离,挑选前 k 个点,进行投票,这 k 个点中,哪个类别的点多,该预测点就被判定 ...

  10. 机器学习算法基础——k近邻算法

    23.k-近邻算法以及案例预测入住位置 24.K-近邻算法案例 分类算法-k近邻算法(KNN) 定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本 ...

最新文章

  1. Android Popwindow 使用
  2. iphone11看信号强度_iPhone11信号怎么样_iPhone11信号差原因|解决办法-太平洋IT百科...
  3. boost::hana::back用法的测试程序
  4. 看看老外的智慧城市都是咋样的
  5. matlab两个曲线的名称怎么显示出来的,求MATLAB的高手,怎么把两张仿真曲线合并显示在一张图上?...
  6. doubango TURN Data Indication报文代码
  7. html——js简单计时器实现
  8. 潇洒郎: websockets 服务端设计:多线程执行async方法
  9. 2022年计算机保研记录(计算所、浙大、华科、东南、北航)
  10. 配置文件(properties类)
  11. 【已解决】打开游戏或者游戏引擎耳机出现滋滋滋的电流声
  12. CorelDRAW2023最新版本图像设计软件
  13. 欧拉角速度和机体角速度
  14. MySql 数字+汉字 排序
  15. MFC ShowWindow参数
  16. 解决Maven打包报错:Failed to clean project: Failed to delete
  17. JDBC,JDBC连接池和JNDI
  18. 浅谈:支付结算系统的重要性
  19. 直播短视频源码,身份证图片识别
  20. 黑马旅游网编写练习(5)--目录的分类展示功能

热门文章

  1. [Linux] 使用 SCP 指令,讓您傳送檔案至遠端、下載檔案
  2. 我常用的find命令
  3. 2、Linux多线程,线程的分离与结合
  4. 活动目录的介绍:深入浅出Active Directory系列(一)
  5. 加入域报错(找不到网络路径)
  6. 【博客管理】博客格式说明【置顶】
  7. 【LeetCode】【字符串】题号:*541. 反转字符串 II
  8. Pycharm下安装Tensorflow问题(利用anaconda)
  9. sns.barplot/sns.countplot/sns.boxplot参数设置
  10. python 常用的几个镜像源