如何解释此回溯代码?

时间:2019-07-09 17:28:21

标签: recursive-backtracking

我很难理解回溯代码。特别是,我知道我们总是在找不到解决方案时进行探索和回溯,但是我不理解path.pop()行背后的逻辑。

我知道我们必须在探索之后弹出元素,但是如何弹出正确的元素呢?

在此之前,我们可能一直递归到子节点

# If current vertex is not destination #Recur for all the vertices adjacent to this vertex for i in self.graph[u]: if visited[i]==False: self.printAllPathsUtil(i, d, visited, path)  那么我们如何保证path.pop()删除u而不删除其他节点?当我绘制一个递归树时这很有意义,但是有一种更简单的方法来理解它吗?

   '''A recursive function to print all paths from 'u' to 'd'. 
    visited[] keeps track of vertices in current path. 
    path[] stores actual vertices and path_index is current 
    index in path[]'''
    def printAllPathsUtil(self, u, d, visited, path): 

        # Mark the current node as visited and store in path 
        visited[u]= True
        path.append(u) 

        # If current vertex is same as destination, then print 
        # current path[] 
        if u ==d: 
            print path 
        else: 
            # If current vertex is not destination 
            #Recur for all the vertices adjacent to this vertex 
            for i in self.graph[u]: 
                if visited[i]==False: 
                    self.printAllPathsUtil(i, d, visited, path) 

        # Remove current vertex from path[] and mark it as unvisited 
        path.pop() 
        visited[u]= False


    # Prints all paths from 's' to 'd' 
    def printAllPaths(self,s, d): 

        # Mark all the vertices as not visited 
        visited =[False]*(self.V) 

        # Create an array to store paths 
        path = [] 

        # Call the recursive helper function to print all paths 
        self.printAllPathsUtil(s, d,visited, path) 

1 个答案:

答案 0 :(得分:0)

printAllPathsUtil每次调用都会收到指向您当前path对象的指针。对printAllPathsUtil的新调用始终是基于迄今为止尚未探索和有效的路径进行的。如果递归函数找到了到达目的地d的位置,则它将打印出完整的当前路径并退后一步,即,路径的最后一个顶点被切除,算法尝试寻找其他路径d的路径(假设您的图形没有重复的顶点,则该路径必须是具有1个以上顶点的“绕道”)。否则,d尚未到达,您将继续探索从u出来的所有顶点,这些顶点已经不在path中(因此您将不返回原点)。一直进行下去,直到测试出从初始s出的所有可能路径为止。

在此过程中,path仅扩展了 ,并尽可能进行了递归,并进行了修剪,以便回溯到较早的状态。换句话说,您在图形中执行depth-first-search,在每个顶点之后分支(即使只有1个)。该算法始终会在回溯之前先耗尽所有可能的路径,因此append-ing和pop-ing是跟踪您进度的正确方法。