数据结构与算法之深度优先 非递归实现 显式栈 / 迭代器模式

数据结构与算法阿木 发布于 2025-07-11 6 次阅读


摘要:

深度优先搜索(Depth-First Search,DFS)是一种常用的图遍历算法,它通过栈这种数据结构来实现。本文将探讨深度优先搜索的非递归实现,包括显式栈和迭代器模式两种方法,并分析其原理、实现方式以及优缺点。

一、

深度优先搜索是一种用于遍历或搜索树或图的算法。它从树的根节点或图的某个节点开始,沿着树的边或图的边遍历,直到达到叶子节点或无法继续前进为止。在遍历过程中,DFS会使用栈来存储待访问的节点,从而实现非递归的遍历方式。

二、显式栈实现深度优先搜索

1. 原理

显式栈实现DFS的基本思想是模拟递归过程,使用栈来存储待访问的节点。在遍历过程中,每次从栈中取出一个节点,访问它,并将其子节点(按照一定的顺序)压入栈中。

2. 实现代码

python

class Stack:


def __init__(self):


self.items = []

def is_empty(self):


return len(self.items) == 0

def push(self, item):


self.items.append(item)

def pop(self):


return self.items.pop()

def peek(self):


return self.items[-1]

def dfs(graph, start):


stack = Stack()


visited = set()

stack.push(start)


while not stack.is_empty():


node = stack.pop()


if node not in visited:


print(node)


visited.add(node)


for neighbor in graph[node]:


if neighbor not in visited:


stack.push(neighbor)

示例图


graph = {


'A': ['B', 'C'],


'B': ['D', 'E'],


'C': ['F'],


'D': [],


'E': ['F'],


'F': []


}

dfs(graph, 'A')


3. 优缺点

优点:

- 非递归实现,避免了递归带来的栈溢出问题。

- 代码简洁,易于理解。

缺点:

- 需要额外的空间来存储栈。

- 遍历顺序可能不如递归实现灵活。

三、迭代器模式实现深度优先搜索

1. 原理

迭代器模式是一种设计模式,它提供了一种访问集合元素的统一方法,而无需暴露集合的内部表示。在DFS中,我们可以使用迭代器模式来模拟递归过程,通过迭代器来访问待访问的节点。

2. 实现代码

python

class Node:


def __init__(self, value):


self.value = value


self.children = []

def add_child(self, child):


self.children.append(child)

def dfs_iterator(root):


stack = [root]


while stack:


node = stack.pop()


yield node.value


for child in reversed(node.children):


stack.append(child)

示例图


root = Node('A')


root.add_child(Node('B'))


root.add_child(Node('C'))


root.children[0].add_child(Node('D'))


root.children[0].add_child(Node('E'))


root.children[1].add_child(Node('F'))


root.children[0].children[0].children[0].add_child(Node('G'))

for value in dfs_iterator(root):


print(value)


3. 优缺点

优点:

- 使用迭代器模式,代码更加简洁,易于维护。

- 可以灵活地控制遍历顺序。

缺点:

- 相比显式栈实现,代码稍显复杂。

- 需要额外的空间来存储迭代器。

四、总结

本文介绍了深度优先搜索的非递归实现,包括显式栈和迭代器模式两种方法。通过分析,我们可以看出两种方法各有优缺点,具体选择哪种方法取决于实际需求。在实际应用中,我们可以根据具体情况选择合适的实现方式,以达到最佳效果。