《算法图解》读书笔记

#广度优先搜索是怎么实现的
每个节点都与邻近节点相连,但是这种链接不一定是一对一,而是多种多样,也可能出现一对多或者多对多或者一对多?
书上说能用散列表表示这种关系?散列表的确可以将键映射到值,但是每个值不是只能映射到一个键吗?注意 我们在这里只关注当前一个节点以及此节点对应的下面的,也就是说只考虑一对多模式,一 代表 键(unique),多 代表 值。如下:
graph={
     }
graph['you']=['alice','bob','clarire']
graph['bob']=['peggy']
graph['alice']=[]
graph['clarire']=[]
以上就是一个典型的有向图 的基础知识 那么深度优先算法是怎么实现的呢?

实现算法:
创建一个队列 用于储存要检查的人
从队列中弹出一个人
检查这个人是不是我们想要的结果
如果是 那么就大功告成 如果不是 就将这个人的所有邻居加入队列
回到第二步:从队列中弹出一个人 这样一直循环下去 直到大功告成
如果最后已经没有什么可以弹出的人了 那么就是说明图中根本没有目标路径

下面是实现算法的具体
from collections import deque
search_queue = deque()#创建一个双端队列
search_queue += graph['you']#把其所有的邻居都加入到搜索队列中

while search_queue:#当队列不为空时
    person = search_queue.popleft()#就取出队列的第一个人
    if person_is_seller(person):#检查其是不是芒果销售商
        #print(person+' is a mango seller')
        return True #是就返回True
    else:#否则,不是的话就将这个人的朋友加入搜索队列
        search_queue += graph[person]
return False #表明没人是芒果销售商

def person_is_seller(name):#这是判断当前元素是不是自己所需要的那个元素 利用相关特征值
    return name[-1] == 'm'
在多对一的情况时 某元素会被添加了两次 因此除了第一次之外都是做无用功,所以每次检查完一个人后,要标记为已检查,否则会导致无限循环。考虑到这一点,最终代码如下:
def search(name):
    search_queue = deque()
    search_queue += graph[name]
    searched = []#此数组用于记录已经检查过的人
    while search_queue:
        person = search_queue.popleft()
        if not person in searched:#仅当这个人没检查过的时候才检查
            if person_is_seller(person):
                return True
            else:
                search_queue += graph[person]
                searched.append(person)#将这个人标间检查过
    return False
infinity = float('inf')
costs={
     }
costs['a'] = 6
costs['b'] = 2
costs['fin'] = infinity

parents = {
     }
parents['a'] = 'start'
parents['b'] = 'start'
parents['fin'] = None
processed =[]
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)#找出来接下来要处理的节点

def find_lowest_cost_node(costs):
    lowest_cost = float('inf')
    lowest_cost_node = node
    for node in costs:
        cost = costs[node]
        if cost < lowest_cost and node not in processed:#如果当前节点开销更低而且未处理过
            lowest_cost = cost
            lowest_cost_node = node
    return  lowest_cost_node
#换言之 如果能有机会到某邻居的距离更短,就更新那条路。从起点到终点每一步都是这样选择的。起点到邻居

#下面来看两个简单的映射函数(从一个数组转换为另一个数组)
arr1 = [1,2,3,4,5]
arr2 = map(lambda x: 2*x ,arr1)

arr1 = #a list of URLS
arr2 = map(download_page, arr1)
#归并函数(将一个数组转化为一个元素)
arr1 = [1,2,3,4,5]
refuce(lambda x,y: x+y, arr1)

你可能感兴趣的:(Reading,Notes)