我正在尝试在这种情况下实现搜索算法: 假设有5个人:0-4人,人们只知道直接在他们之下工作的人。例如,人员0和1无人管理,人员2管理人员0,人员3管理人员1,而人员4同时管理人员2和3。
假设我将此层次结构存储在称为层次结构hierarchy = [[],[],[0],[1],[2,3]]
我要寻找的是谁在任意一个人下直接或间接工作,在这种情况下,直接和间接在4岁以下工作的人应该是0、1、2、3或[0,1,2,3] = allUnder(hierarchy,ID = 4)
。 / p>
我认为该问题的解决方案是某种递归搜索,但是我对递归非常模糊。我正在寻找的算法在重复值的情况下也应该是高效的(例如,假设3同时管理0,1,答案仍应为0,1,2,3)。
我知道我应该把解决方案放在第一位,但是我现在真的不知道如何解决它。任何帮助将不胜感激。
更新:我也非常有兴趣寻找特定人的所有直接或间接管理方式。
答案 0 :(得分:3)
鉴于您想要双向搜索(即能够同时搜索下属和经理),您将需要某种树形结构来编码其节点之间的双向链接。这是实现这种树的类:
class Node:
def __init__(self, val):
"""initialize a node with the worker id value
"""
self._children = []
self._parent = None
self.val = val
def link(self, *node):
"""create a parent-child link between this (parent) node and one
or more (children) nodes
"""
for n in node:
n._parent = self
self._children.append(n)
def get(self):
"""depth-first recursive get
"""
return [x for y in ([n.val] + n.get() for n in self._children) for x in y]
def getparents(self):
"""walks up parents (currently there's at most one parent per-node)
"""
return [] if self._parent is None else [self._parent.val] + self._parent.getparents()
class Tree:
def __init__(self, idlists):
"""initialize the tree as per the OP's example input
"""
self._nodes = {}
for topid,idlist in enumerate(idlists):
self.add(topid, idlist)
def __getitem__(self, key):
return self._nodes[key]
def _getnode(self, i):
"""get or create the node with id=i.
Avoid constructing new Nodes if we don't have to
"""
if i in self._nodes:
return self._nodes[i]
else:
n = self._nodes[i] = Node(i)
return n
def add(self, topid, idlist):
"""create a node with id=topid (if needed), then add
child nodes, one per entry in idlist
"""
self._getnode(topid).link(*(self._getnode(i) for i in idlist))
以下是使用上面定义的Tree
类来解决您指定的问题的方法:
data = [[],[],[0],[1],[2,3]]
people = Tree(data)
## get subordinates
print(people[4].get())
# output: [2, 0, 3, 1]
print(people[2].get())
# output: [0]
print(people[1].get())
# output: []
## get managers
print(people[1].getparents())
# output: [3, 4]
print(people[2].getparents())
# output: [4]
print(people[4].getparents())
# output: []
这是一个经典的CS栗子,在现代编码教程中似乎没有太多的了解(我认为是因为以前用树解决的许多问题现在都具有基于哈希表/ dict的更简单的答案)。
答案 1 :(得分:1)
使用诸如数据结构之类的邻接表将这个问题表示为有向图。按照您的假设,3处理0和1。
graph = {4:[2,3],2:[0],3:[0,1]}
使用深度优先搜索(DFS)或呼吸优先搜索(BFS)遍历来列出在某人下进行举报的人。
DFS(graph [2])应该返回0
DFS(graph [4])应该返回0、2、1、3
BFS(graph [4])应该返回2、3、0、1
答案 2 :(得分:1)
如果我们假设自上而下的层次结构,就足够了:
people = [[],[],[0],[1],[2,3]]
def manages(manager, people):
lst = people[manager]
for employee in lst:
lst = lst + manages(employee, people)
return lst
print(set(manages(4, people)))
输出:{0, 1, 2, 3}
这是工作中的example。
如果输入列表中存在循环关系,则此解决方案不会终止。
答案 3 :(得分:0)
我正在将层次结构想象成字典:
hierarchy = { 4: { 2: 0, 3: 1 } }
在这里我可以定义一个递归方法来获取孩子:
def get_all_children(father, res=None):
if res == None: res = []
res.extend(father.keys())
for child in father.values():
if not isinstance(child, dict):
res.append(child)
else: get_all_children(child, res)
return res
那我可以打电话给
print(get_all_children(hierarchy[4]))
#=> [2, 3, 0, 1]
hierarchy = {5: { 4: {2: 0, 3: 1} }, 8: {7: 6} }
print(get_all_children(hierarchy[5]))
#=> [4, 2, 3, 0, 1]