c语言狄克斯特拉算法,数据结构复习(python)——狄克斯特拉算法(Dijkstra)

学习材料

《算法图解》第7章

适用情景

找出从一个节点到另一个节点的最短(快)路径

准备工作

对一个带权图进行描述,可使用两个散列表(字典),其中一个散列表用来描述每个结点的指向及权值,对于一个节点指向两个及以上的节点的情况,可使字典嵌套;另一个散列表用来描述从“起点”开始到其他节点的距离,若起点未与某个节点直接相连,在初始时把这段距离置为无穷大。

举例:图及其对应散列表如下

4a4ed4d28706cdfb3145796aab9b880a.png

graph={}

graph["start"]={}

graph["start"]["A"]=5

graph["start"]["B"]=2

graph["A"]={}

graph["A"]["C"]=4

graph["A"]["D"]=2

graph["B"]={}

graph["B"]["A"]=8

graph["B"]["D"]=7

graph["C"]={}

graph["C"]["fin"]=3

graph["C"]["D"]=6

graph["D"]={}

graph["D"]["fin"]=1

graph["fin"]={}

costs={}

costs["A"]=5

costs["B"]=2

costs["C"]=float('inf')

costs["D"]=float('inf')

costs["fin"]=float('inf')

为了记录最短路径,还需要一个散列表描述最短路径中的父子关系。

parents={}

parents["A"]="start"

parents["B"]="start"

parents["C"]=""

parents["D"]=""

parents["fin"]=""

执行算法时,将不断更新costs和parents。

算法流程

(1)找出costs中对应值最小的结点,且未被处理过(未在processed中)

(2)检查该节点的邻居,寻找是否有从起点开始经过该节点到其邻居的更短路径,若有,则更新其邻居在costs的对应值

(3)重复(1)(2),直到对每个节点都做过这件事

(4)计算最短路径

代码如下:

processed=[]

def find_lowest_cost_node(costs):

lowest_cost=float('inf')

lowest_cost_node=None

for node in costs: #遍历所有节点

cost=costs[node]

if costnewcost: #如果经过当前节点前往该邻居更近

costs[n]=newcost #则更新起点到该邻居的距离(所谓的该邻居的开销)

parents[n]=node #同时将该邻居的父节点设置为当前节点

processed.append(node) #当前节点标记为已处理

node=find_lowest_cost_node(costs) #找出下一个在costs中的最小开销节点,进入下一轮循环

输出最短路径及最短距离(测试):

def lowest_path(parents):

record=["fin",]

child=parents["fin"]

while child != "start":

record.append(child)

child=parents[child]

record.append("start")

record.reverse()

return record

def tatal_weight(record):

record1=record[1::]

sum=0

for i in range(len(record1)):

sum=sum+graph[record[i]][record1[i]]

return sum

print(lowest_path(parents))

print(tatal_weight(lowest_path(parents)))

输出结果

['start', 'A', 'D', 'fin']

8

算法弊端

(1)不能用于有负权值的图,因为在该算法中,已处理过的点意味着从起点到该点的开销已是最小,且不会再对该点进行处理,但负权值可能会拉低这个最小开销。

(2)不能使用于有环图。只适用于有向无环图。

(3)有负权值的图可使用贝尔曼—福德算法,非加权图可使用广度优先搜索算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值