最短路径

在一个带权图中,顶点V0到图中任意一个顶点Vi的一条路径所经过边上的权值之和,定义为该路径的带权路径长度,把带权路径最短的那条路径称为最短路径。
如图所示,求双子峰到金门大桥的最短距离。

此类问题要用到狄克斯特拉(DiskStra)算法

使用狄克斯特拉(DiskStra)算法

图中每个数字都是时间,为此找出从起点到终点用时最短的路径。

如果你使用广度优先搜索,广度优先搜索算法BFS讲解以及python 实现
你将得到下面这条段数最少的路径。

这条路径耗费7分钟,我们接下来找找还有没有更短的路径。
狄克斯特拉(DiskStra)算法 包含4个步骤:

  1. 找出可在最短时间内到达的点
  2. 更新该节点的邻居的开销
  3. 重复计算该过程,直到对所有节点都做了
  4. 计算最终路径

第一步:你站在起点,可以走的点是A,B。到达A需要6分钟,到达B需要2分钟,其他节点不能到达,设为无穷。

第二步:因为起点到B最近,然后计算B前往各邻居的距离
B到A的距离是3,我们找到一条前往A点的更短路径5,从起点直接前往A点距离是6,则更新库中起点到A的距离。

对于节点B的邻居,如果找到前往它的更短路径,就更新其开销,在这里我们找到了:前往A点的更短路径,时间由6分钟缩短到了5分钟;前往终点的更短路径,时间由无穷大缩短到7分钟。

第三步:重复
重复第一步,找出最短时间可以到达的点,前面对节点B执行了第二步,除B点外,还有节点A

重读第二步,更新节点A所有邻居的开销

你发现前往终点的时间为6分钟。

对每个节点都应用狄克斯特拉(DiskStra)算法,现在知道前往B节点2分钟,A分钟,终点6分钟。

狄克斯特拉(DiskStra)算法适用于有向无环图。

算例1实现

以图为例

第一步:解决这个问题,需要准备三个散列表

第一个散列表表示图,依次是父节点,子节点,权重。第一个散列表图可以用散列表嵌套表示。

"""     、、、、、、  第一个散列表  用于表示图   、、、、、、     """
graph={}
#起点 到各邻居的关系
graph["start"]={}
graph["start"]["a"]=6
graph["start"]["b"]=2
#print(graph["start"].keys())#dict_keys(['a', 'b'])
#节点a到各邻居关系
graph["a"]={}
graph["a"]["fin"]=1#节点b到各邻居关系
graph["b"]={}
graph["b"]["a"]=3
graph["b"]["fin"]=5#终点与各邻居关系
graph["fin"]={}#终点没有邻居

第二个散列表为初始时起点出发到各节点的距离,随着算法进行需要不断更新。

""" 第二个散列表 节点的开销。节点的开销表示起点出发到该节点需要多少时间"""
infinity=float("inf")#无穷大
costs={}
costs['a']=6
costs['b']=2
costs['fin']=infinity

第三个散列表。左边为子节点,右边为父节点,用来表示路径。随着算法进行需要不断更新,是针对出发点建立的

""" 第三个散列表 存储 路径 . parents['a']="start"表示节点a的上一节点是start,如果后面发现更短路径,可以修改为parents['a']=b"""
parents={}
parents['a']="start"
parents['b']="start"
parents['fin']=None#出发点不能直接到达

第二步:需要一个数组,存储已经处理过的节点

"""                        需要一个数组,存储已经处理过的节点 """
processed=[]

第三步:最小开销节点函数

"""                        开销最小的函数 """
def find_lowest_cost_node(costs):lowest_cost=float('inf')lowest_cost_node=Nonefor node in costs:#遍历每个节点cost=costs[node]if cost<lowest_cost and node not in processed:#如果当前节点小于最小开销,且没有处理过lowest_cost_node=node #则将该节点设为最小开销节点lowest_cost=cost#更新最小开销return lowest_cost_node

第四步:DiskStra算法

""" DiskStra算法"""
node=find_lowest_cost_node(costs) #在未处理的节点中找到开销最小的节点,即离出发点最近的点
while node  is not None: #这个循环表示所有节点处理过才会结束cost=costs[node]neighbors=graph[node]for n in neighbors.keys():#遍历当前节点的所有邻居new_cost=cost+neighbors[n]if costs[n]>new_cost:#如果经当前节点离该邻居更近costs[n]=new_cost#就更新该节点的开销parents[n]=node #同时将该邻居的父节点设置为该节点processed.append(node)#将该节点标记为处理过node=find_lowest_cost_node(costs) #查找接下来要循环处理的点,并循环

全部代码


"""       第一个散列表  用于表示图        """
graph={}
#起点 到各邻居的关系
graph["start"]={}
graph["start"]["a"]=6
graph["start"]["b"]=2
#print(graph["start"].keys())#dict_keys(['a', 'b'])
#节点a到各邻居关系
graph["a"]={}
graph["a"]["fin"]=1#节点b到各邻居关系
graph["b"]={}
graph["b"]["a"]=3
graph["b"]["fin"]=5#终点与各邻居关系
graph["fin"]={}#终点没有邻居""" 第二个散列表 节点的开销。节点的开销表示起点出发到该节点需要多少时间,每个节点都要列出来"""
infinity=float("inf")#无穷大
costs={}
costs['a']=6
costs['b']=2
costs['fin']=infinity""" 第三个散列表 存储 路径 . parents['a']="start"表示节点a的上一节点是start,如果后面发现更短路径,可以修改为parents['a']=b,每个节点都要列出来"""
parents={}
parents['a']="start"
parents['b']="start"
parents['fin']=None#出发点不能直接到达"""                        需要一个数组,存储已经处理过的节点 """
processed=[]"""                        开销最小的函数 """
def find_lowest_cost_node(costs):lowest_cost=float('inf')lowest_cost_node=Nonefor node in costs:#遍历每个节点cost=costs[node]if cost<lowest_cost and node not in processed:#如果当前节点小于最小开销,且没有处理过lowest_cost_node=node #则将该节点设为最小开销节点lowest_cost=cost#更新最小开销return lowest_cost_node""" DiskStra算法"""
node=find_lowest_cost_node(costs) #在未处理的节点中找到开销最小的节点,即离出发点最近的点
while node  is not None: #这个循环表示所有节点处理过才会结束cost=costs[node]neighbors=graph[node]for n in neighbors.keys():#遍历当前节点的所有邻居new_cost=cost+neighbors[n]if costs[n]>new_cost:#如果经当前节点离该邻居更近costs[n]=new_cost#就更新该节点的开销parents[n]=node #同时将该邻居的父节点设置为该节点processed.append(node)#将该节点标记为处理过node=find_lowest_cost_node(costs) #查找接下来要循环处理的点,并循环#打印结果
print('costs',costs)
print('parents',parents)

流程图解

找到开销最少的点

获取该节点的开销和邻居

遍历邻居

每个节点都要开销,开销指从起点到该节点需要多长时间,在这里,将计算从起点到B再到A的开销,而不是直接到A的开销

和原始开销进行对比

找到一条前往节点A的更短路径,更新节点A的开销 这条路径由B到A,由此更新节点A的父节点

现在回到for循环,下一个邻居是终点

经节点B前往终点需要7分钟,

原始终点节点开销为无穷大,现在7分钟,更新终点节点的开销和父节点

现在将节点B设为被处理过的

接下来要处理的点

获取节点A的开销和邻居

节点A只有一个邻居,终点。当前前往终点需要7分钟,经过节点A需要多久,见图

更短,更新终点的开销和父节点

节点A被添加进处理过的。
接下来要处理的点为终点fin。
终点fin没有邻居,不更新,然后显示终点也被添加进处理过的。
node变为空,退出while循环。结束。

如果要改变起点,如起点改到A,再来探讨该问题。只需修改costs和parents散列表即可。
算例1借鉴:《算法图解》

算例2实现

算例1用到的数据结构是散列表,本例子用矩阵来做。

第一步:定义图和拓扑结构

"""   一.定义图   """
### ====================给一个所有节点的列表
list_nodes_id = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
### ==================== 给一个拓扑的常数矩阵.
fin= float('inf') # 无穷大。这意味着没有联系。
### fin_topo是表示拓扑的二维邻接矩阵
fin_topo = [[fin, 2.9, 2.5, fin, 2, fin, 1.8, 3, 1.8, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 0[2.9, fin, 1.3, fin, fin, 1.7, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 1[1, 1, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 2[fin, fin, 1, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 3[1, fin, fin, 1, fin, fin, fin, fin, fin, 1, 1, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 4[fin, 1, fin, fin, fin, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 5[1, fin, fin, fin, fin, 1, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 6[1, fin, fin, fin, fin, fin, 1, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 7[1, fin, fin, fin, fin, fin, fin, 1, fin, 1, fin, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin],  # 8[fin, fin, fin, fin, 1, fin, fin, fin, 1, fin, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 9[fin, fin, fin, fin, 1, fin, fin, fin, fin, fin, fin, 1, fin, 1, fin, fin, fin, fin, fin, fin, fin],  # 10[fin, fin, fin, fin, 1, fin, fin, fin, fin, 1, 1, fin, fin, 1, 1, fin, fin, fin, fin, fin, fin],  # 11[fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, fin, fin, fin, fin, 1, fin, fin, fin, fin, fin, fin],  # 12[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, 1, fin, fin, 1, fin, fin, 1, 1, fin, fin],  # 13[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, 1, 1, fin, 1, 1, fin, fin, fin, fin],  # 14[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, 1, fin, 1, 1, fin],  # 15[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, 1, fin, fin, fin, fin, 1],  # 16[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, fin, fin, fin, 1, fin, fin],  # 17[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, 1, fin, 1, fin, 1, fin],  # 18[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, fin, 1, fin, 1],  # 19[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, fin, 1, fin],  # 20
]### --- 读取拓扑,并生成给定拓扑中的所有边。
edges = []
for i in range(len(fin_topo)):for j in range(len(fin_topo[0])):if i != j and fin_topo[i][j] != fin:edges.append((i, j, fin_topo[i][j]))  ### (i,j) 是一个链接;fin_topo[i][j]这里是1,链接的长度(i,j).
#print(edges)
#[(0, 1, 2.9), (0, 2, 2.5), (0, 4, 2), (0, 6, 1.8), (

edges

第二步 算法

"""算法实现"""
from collections import defaultdict
from heapq import *#heapq 堆,一般指最小堆
"""
heap = [1,3,4,2,6,8,9]
heapq.heapify(heap)
# heap = [1,2,4,3,6,8,9]
"""
"""
g
{0: [(2.9, 1), (2.5, 2), (2, 4), (1.8, 6), (3, 7), (1.8, 8)], 1: [(2.9, 0), (1.3, 2), (1.7, 5)], 2: [(1, 0), (1, 1), (1, 3)], 3: [(1, 2), (1, 4)], 4: [(1, 0), (1, 3), (1, 9), (1, 10), (1, 11)], 5: [(1, 1), (1, 6)], 6: [(1, 0), (1, 5), (1, 7)], 7: [(1, 0), (1, 6), (1, 8)], 8: [(1, 0), (1, 7), (1, 9), (1, 12)], 9: [(1, 4), (1, 8), (1, 11)], 10: [(1, 4), (1, 11), (1, 13)], 11: [(1, 4), (1, 9), (1, 10), (1, 13), (1, 14)], 12: [(1, 8), (1, 14)], 13: [(1, 10), (1, 11), (1, 14), (1, 17), (1, 18)], 14: [(1, 11), (1, 12), (1, 13), (1, 15), (1, 16)], 15: [(1, 14), (1, 16), (1, 18), (1, 19)], 16: [(1, 14), (1, 15), (1, 20)], 17: [(1, 13), (1, 18)], 18: [(1, 13), (1, 15), (1, 17), (1, 19)], 19: [(1, 15), (1, 18), (1, 20)], 20: [(1, 16), (1, 19)]})"""def dijkstra_raw(edges, from_node, to_node):g = defaultdict(list)#使用list作第一个参数,可以很容易将键-值对序列转换为列表字典。for l, r, c in edges:g[l].append((c, r))q, seen = [(0, from_node, ())], set()#q=[(0, from_node, ())],q为当前节点创建一个堆while q:(cost, v1, path) = heappop(q)#删除q中的顶if v1 not in seen:#如果V1没有被查看,V1为出发点seen.add(v1)#将V1添加进已查看path = (v1, path)#(点,路径)if v1 == to_node:#如果当前点是目标点return cost, path#返回距离和路径for c, v2 in g.get(v1, ()):#遍历V1的所有邻居 c为到邻居的距离,V2为邻居if v2 not in seen:heappush(q, (cost + c, v2, path))#修改起点到V2的距离return float("inf"), []

全部代码

"""   一.定义图   """
# ====================给一个所有节点的列表
list_nodes_id = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
### ==================== 给一个拓扑的常数矩阵.
fin= float('inf') # 无穷大。这意味着没有联系。
#fin_topo是表示拓扑的二维邻接矩阵
fin_topo = [[fin, 2.9, 2.5, fin, 2, fin, 1.8, 3, 1.8, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 0[2.9, fin, 1.3, fin, fin, 1.7, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 1[1, 1, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 2[fin, fin, 1, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 3[1, fin, fin, 1, fin, fin, fin, fin, fin, 1, 1, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 4[fin, 1, fin, fin, fin, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 5[1, fin, fin, fin, fin, 1, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 6[1, fin, fin, fin, fin, fin, 1, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 7[1, fin, fin, fin, fin, fin, fin, 1, fin, 1, fin, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin],  # 8[fin, fin, fin, fin, 1, fin, fin, fin, 1, fin, fin, 1, fin, fin, fin, fin, fin, fin, fin, fin, fin],  # 9[fin, fin, fin, fin, 1, fin, fin, fin, fin, fin, fin, 1, fin, 1, fin, fin, fin, fin, fin, fin, fin],  # 10[fin, fin, fin, fin, 1, fin, fin, fin, fin, 1, 1, fin, fin, 1, 1, fin, fin, fin, fin, fin, fin],  # 11[fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, fin, fin, fin, fin, 1, fin, fin, fin, fin, fin, fin],  # 12[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, 1, fin, fin, 1, fin, fin, 1, 1, fin, fin],  # 13[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, 1, 1, fin, 1, 1, fin, fin, fin, fin],  # 14[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, 1, fin, 1, 1, fin],  # 15[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, 1, fin, fin, fin, fin, 1],  # 16[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, fin, fin, fin, 1, fin, fin],  # 17[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, 1, fin, 1, fin, 1, fin],  # 18[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, fin, 1, fin, 1],  # 19[fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, fin, 1, fin, fin, 1, fin],  # 20
]#--- 读取拓扑,并生成给定拓扑中的所有边。
edges = []
for i in range(len(fin_topo)):for j in range(len(fin_topo[0])):if i != j and fin_topo[i][j] != fin:edges.append((i, j, fin_topo[i][j]))  ### (i,j) 是一个链接;fin_topo[i][j]这里是1,链接的长度(i,j).
#print(edges)
#[(0, 1, 2.9), (0, 2, 2.5), (0, 4, 2), (0, 6, 1.8), (#算法实现
from collections import defaultdict
from heapq import *def dijkstra_raw(edges, from_node, to_node):g = defaultdict(list)#使用list作第一个参数,可以很容易将键-值对序列转换为列表字典。for l, r, c in edges:g[l].append((c, r))q, seen = [(0, from_node, ())], set()#q=[(0, from_node, ())],q为当前节点创建一个堆while q:(cost, v1, path) = heappop(q)#删除q中的顶if v1 not in seen:#如果V1没有被查看,V1为出发点seen.add(v1)#将V1添加进已查看path = (v1, path)#(点,路径)if v1 == to_node:#如果当前点是目标点return cost, path#返回距离和路径for c, v2 in g.get(v1, ()):#遍历V1的所有邻居 c为到邻居的距离,V2为邻居if v2 not in seen:heappush(q, (cost + c, v2, path))return float("inf"), []start = int(input("请输入起始点:"))
end = int(input("请输入终点:"))
print("=== Dijkstra算法 ===")
print("找从 %s 到 %s的最短路径:" % (start, end))
length, path_queue = dijkstra_raw(edges,start, end)#path_queue路径
print('距离',length)
print('路径',path_queue)

0到15的距离为4.8,路径0-8-12-14-15

工具包讲解

参考我以前的博文
最短路径Dijkstra讲解,工具包使用 python

作者:电气-余登武

用图讲解狄克斯特拉(DiskStra)算法,python实现 。相关推荐

  1. 狄克斯特拉(Dijkstra)算法详解

    1.前言 最近在看<算法图解>,其中第七章狄克斯特拉算法个人感觉并没有讲的清楚,比如看完7.1节给人的感觉是狄克斯特拉算法会遍历图中的每一条边,后续狄克斯特拉不适用负权边的说法就站不住脚了 ...

  2. 狄克斯特拉(Dijkstra)算法原理详细解释与实现(python)

    目录 写在前面 1. 简介 2. 原理 2.1 找出最便宜的节点 2.2 计算前往该节点的各个邻居的开销 2.3 重复上面的步骤 实现 总结 写在前面 本文原理摘自<算法图解>这本书. 其 ...

  3. 算法快学笔记(十三):狄克斯特拉(Dijkstra)算法原理与实现

    1. 简介 广度优先算法可以找出段数最少的路径,但是对于路径上带权重的图,想要找出最快的路径,则需要使用狄克斯特拉算法. 2. 原理 为了说明狄克斯特拉算法的原理,使用换钢琴的的例子来做说明. 假设R ...

  4. Python图算法之狄克斯特拉算法

    可用于类似公交线路用时最短的案例. 图算法之狄克斯特拉算法(Dijkstra's algorithm),包含4个步骤: (1) 找出"最便宜"的节点(权重最小),即可在最短时间内前 ...

  5. Python查找算法之狄克斯特拉算法

    目录 简介 加权图 非加权图 思路 实例 代码步骤 代码示例 运行结果 简介 狄克斯特拉算法解决了耗时最短(总权重最小)问题狄克斯特拉算法适用于加权图,并且图为有向无环图(DAG),而且权重不能为负数 ...

  6. 狄克斯特拉算法——python实现

    文章目录 狄克斯特拉算法 原理概述 相关术语: 实例研究--换钢琴 代码实现 总结 狄克斯特拉算法 原理概述 加权图--提高或降低某些边的权重 狄克斯特拉算法包括四个步骤: 1.找出"最便宜 ...

  7. 狄克斯特拉算法(入门)

    狄克斯特拉算法可以找出加权图中前往X的最短路径. 注意: - 其只适用于有向无环图 - 适用于正权边,负权边的将出错(贝尔曼-福德算法适用于负权边) 步骤: 找出当前最"便宜"的节 ...

  8. 小白的算法初识课堂(part7)--狄克斯特拉算法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 狄克斯特拉算法 具体步骤实现 术语 跳蚤市场 具体步骤实现 负权边 python实现 狄克斯特拉算法 在上一个 ...

  9. 图解算法学习笔记(七):狄克斯特拉算法

    目录 1)使用狄克斯特拉算法 2)术语 3)实现 4)小结 本章内容; 介绍加权图,提高或降低某些边的权重: 介绍狄克斯特拉算法,找出加权图中前往X的最短路径: 介绍图中的环,它导致狄克斯特拉算法不管 ...

最新文章

  1. python3 动态创建类对象并调用函数
  2. oracle locked time,Oracle里面的用户smsdb无法登录 LOCKED(TIMED)
  3. 学院派CAD工具箱及CAD调用外部应用程序的方法
  4. LoadRunner Interview Questions
  5. Sys.WORD_SIZE Julia中的常量
  6. python之路day5_Python语言之python之路笔记day19
  7. 【GRE协议】CentOS配置GRE隧道
  8. ext4.0.7 样式兼容性
  9. android4.3模拟器,天心安卓模拟器
  10. vb6实现下载带进度
  11. java jni 傻瓜教程
  12. (附源码)php初中历史专题教学网站 毕业设计 100623
  13. 数据结构-银行业务模拟系统
  14. 澳大利亚维多利亚州旅游局力推高尔夫主题体验
  15. 计算机中的标准差是哪个英语单词,标准差是什么意思
  16. Unity拼图小游戏
  17. 变声算法实现(基频追踪+SOLA)
  18. 2020最新苹果企业级开发者账号续费流程
  19. 最危险的计算机命令,十大危险cmd指令
  20. 多边形画椭圆算法java_运用椭圆画法,45行代码画出随意正多边形

热门文章

  1. Tomcat线程连接池参数优化
  2. jfinal使用render之后还会继续往下执行代码吗
  3. PaddleOCR——DEMO
  4. Cython——[AttributeError: ‘MSVCCompiler‘ object has no attribute ‘compiler_so‘]解决方案
  5. C#——《C#语言程序设计》实验报告——继承与多态——电视和电灯委托
  6. C++——《算法分析与设计》实验报告——最长公共子序列问题
  7. Eclipse——添加库(Add Library)到项目
  8. BugKuCTF WEB 成绩单
  9. java biginteger位数,Java之BigInteger(面试题12:打印1到最大的n位数)
  10. 操作系统 第二章【记录型信号量机制、独木桥问题】【MOOC答案】