python中的递归搜索

时间:2019-01-19 20:45:54

标签: python numpy recursion

我正在尝试在这种情况下实现搜索算法: 假设有5个人:0-4人,人们只知道直接在他们之下工作的人。例如,人员0和1无人管理,人员2管理人员0,人员3管理人员1,而人员4同时管理人员2和3。

The described hierarchy

假设我将此层次结构存储在称为层次结构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)。

我知道我应该把解决方案放在第一位,但是我现在真的不知道如何解决它。任何帮助将不胜感激。

更新:我也非常有兴趣寻找特定人的所有直接或间接管理方式。

4 个答案:

答案 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]