在非二叉树中查找从根到叶的每条路径的优化方法

时间:2017-02-25 19:12:01

标签: python arrays algorithm runtime

我有一个2D数组,它将后向指针列表存储到同一个数组中的某些位置。我需要从2d数组的最后一个条目遍历到没有存储任何backpointer的条目。从技术上讲,它就像遍历非二叉树一样。

我目前的天真实施是

def traverse_tree (root,cur_path,backpointer_array,pathlist):
    print "adding root " + str(root)
    cur_path.append(root)
    children = backpointer_array[root[0]][root[1]]
    if(len(children)==0):
        pathlist.append(cur_path)
    else:
        for child in children:          
            traverse_tree(child,cur_path[:],backpointer_array,pathlist)

当矩阵的大小很小时,代码工作正常[5 * 5],但是当我尝试用更大的矩阵[50 * 500]运行代码时,代码需要永远执行。有没有办法优化此实现

2 个答案:

答案 0 :(得分:1)

使用动态编程在内存中存储可以重复使用的“子路径”

您将需要一个映射M,它将数组的每个节点映射到该节点的路径列表。

如果您的数据结构是树,则不会获得任何结果,但在一般情况下,您可以从指数时间变为线性

伪代码

M = map<Node, List<Path>> // Path is just a list of Nodes
List<Path> traverse_tree (CurrentNode)
    if(M contains CurrentNode)
        return M[CurrentNode]
    answer = List<Path>
    for each children C of CurrentNode
        subpath = traverse_tree(C)
        // Shorthand to say prepend CurrentNode to all paths in subpath
        answer.append(CurrentNode+subpath) 
    M[CurrentNode] = answer // Dynamic programming time!
    return answer

Full_Path_List_From_Root = traverse_tree(Root)

注意:

  • 如果有一个循环,这可以无限循环(但请注意,无论如何都无法在有限的时间内获得所有路径)。
  • 每个节点只进行一次探索
  • 这是一个有趣的例子

Example where naive implementation is exponential

想象一下,有2个节点的N个堆栈(图中只有3个)。总共有2 ^ N个路径。天真的实现访问叶子指数的时间。如果存储子路径,则只访问每个节点一次而不是指数时间(但是,没有奇迹,如果存在指数路径,则路径列表将呈指数级)

答案 1 :(得分:0)

如果您将使用多线程和队列,则可以获得更好的性能。

这是一个使用示例,您应该重写它并在您的场景中实现它,如果您需要帮助,我将非常乐意提供帮助。

这是一个简单的演示:

from Queue import Queue
from threading import Thread

# Set up some global variables
worker_threads = 64
my_queue = Queue()

# the data we work on
my_data = range(1000)

def Worker(i, q,):
    # This is the worker thread function. 
    # It processes items in the queue one after another.  
    # These daemon threads go into an infinite loop, 
    # and only exit when the main thread ends.
    while True:
        data = q.get()

        print "[*] ", data, " i am", i

        q.task_done()


# Set up some threads to fetch the enclosures
for i in range(worker_threads):
    worker = Thread(target=Worker, args=(i, my_queue,))
    worker.setDaemon(True)
    worker.start()

# Put the enclosure data into the queue.
for data in my_data:
    my_queue.put(data)

# Now wait for the queue to be empty, indicating that we have processed all of the data.
print '*** Main thread waiting'
my_queue.join()
print '*** Done'