数据结构和算法

DSA 主页 DSA 概述 DSA 环境设置 DSA 算法基础 DSA 渐近分析

数据结构

DSA 数据结构基础 DSA 数据结构和类型 DSA 数组数据结构

链接列表

DSA 链接列表数据结构 DSA 双向链接列表数据结构 DSA 循环链表数据结构

堆栈 &队列

DSA 堆栈数据结构 DSA 表达式解析 DSA 队列数据结构

搜索算法

DSA 搜索算法 DSA 线性搜索算法 DSA 二分搜索算法 DSA 插值搜索 DSA 跳跃搜索算法 DSA 指数搜索 DSA 斐波那契搜索 DSA 子列表搜索 DSA 哈希表

排序算法

DSA 排序算法 DSA 冒泡排序算法 DSA 插入排序算法 DSA 选择排序算法 DSA 归并排序算法 DSA 希尔排序算法 DSA 堆排序 DSA 桶排序算法 DSA 计数排序算法 DSA 基数排序算法 DSA 快速排序算法

图形数据结构

DSA 图形数据结构 DSA 深度优先遍历 DSA 广度优先遍历 DSA 生成树

树数据结构

DSA 树数据结构 DSA 树遍历 DSA 二叉搜索树 DSA AVL 树 DSA 红黑树 DSA B树 DSA B+ 树 DSA 伸展树 DSA 尝试 DSA 堆数据结构

递归

DSA 递归算法 DSA 使用递归的汉诺塔 DSA 使用递归的斐波那契数列

分而治之

DSA 分而治之 DSA 最大最小问题 DSA 施特拉森矩阵乘法 DSA Karatsuba 算法

贪婪算法

DSA 贪婪算法 DSA 旅行商问题(贪婪方法) DSA Prim 最小生成树 DSA Kruskal 最小生成树 DSA Dijkstra 最短路径算法 DSA 地图着色算法 DSA 分数背包问题 DSA 作业排序截止日期 DSA 最佳合并模式算法

动态规划

DSA 动态规划 DSA 矩阵链乘法 DSA Floyd Warshall 算法 DSA 0-1 背包问题 DSA 最长公共子序列算法 DSA 旅行商问题(动态方法)

近似算法

DSA 近似算法 DSA 顶点覆盖算法 DSA 集合覆盖问题 DSA 旅行商问题(近似方法)

随机算法

DSA 随机算法 DSA 随机快速排序算法 DSA Karger 最小割算法 DSA Fisher-Yates 洗牌算法

DSA 有用资源

DSA 问答 DSA 快速指南


深度优先搜索 (DFS) 算法

深度优先搜索 (DFS) 算法

深度优先搜索 (DFS) 算法是一种递归算法,用于搜索图或树数据结构的所有顶点。该算法以深度方向遍历图,并使用堆栈记住在任何迭代中出现死角时获取下一个顶点以开始搜索。

深度优先遍历

如上例所示,DFS 算法首先从 S 遍历到 A、D、G、E、B,然后到 F,最后到 C。它采用以下规则。

  • 规则 1 −访问相邻的未访问顶点。将其标记为已访问。显示它。将其压入堆栈。

  • 规则 2 − 如果未找到相邻顶点,则从堆栈中弹出一个顶点。(它将弹出堆栈中所有没有相邻顶点的顶点。)

  • 规则 3 − 重复规则 1 和规则 2,直到堆栈为空。

步骤 遍历 描述
1 深度优先搜索第一步 初始化堆栈。
2 深度优先搜索第二步 将 S 标记为已访问并将其放入堆栈。探索 S 中任何未访问的相邻节点。我们有三个节点,可以从中选取任意一个。在本例中,我们将按字母顺序选取节点。
3 深度优先搜索步骤三 将 A 标记为已访问,并将其放入堆栈。探索 A 节点的任何未访问相邻节点。S 和 D 都与 A 相邻,但我们只关注未访问的节点。
4 深度优先搜索步骤四 访问 D 并将其标记为已访问,然后放入堆栈。这里,我们有 B 和 C 节点,它们与 D 相邻,并且都未访问过。不过,我们还是要按字母顺序选择。
5 深度优先搜索第五步 我们选择B,将其标记为已访问并放入堆栈。此处B没有任何未访问的相邻节点。因此,我们从堆栈中弹出 B。
6 深度优先搜索第六步 我们检查堆栈顶部是否返回到上一个节点,并检查它是否有任何未访问的节点。这里,我们发现 D 位于栈顶。
7 深度优先搜索步骤 7 现在唯一来自 D 的未访问相邻节点是 C。因此,我们访问 C,将其标记为已访问,然后将其放入栈中。

由于 C 没有任何未访问的相邻节点,因此我们不断弹出堆栈,直到找到一个具有未访问相邻节点的节点。在这种情况下,没有元素,我们会不断弹出,直到堆栈为空。

示例

以下是深度优先搜索 (DFS) 算法在各种编程语言中的实现 −

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX 5
struct Vertex {
   char label;
   bool visited;
};
//堆栈变量
int stack[MAX];
int top = -1;
//图变量
//顶点数组
struct Vertex* lstVertices[MAX];
//邻接矩阵
int adjMatrix[MAX][MAX];
//顶点数量
int vertexCount = 0;
//堆栈函数
void push(int item) { 
   stack[++top] = item; 
} 
int pop() { 
   return stack[top--]; 
} 
int peek() {
   return stack[top];
}
bool isStackEmpty() {
   return top == -1;
}
//图函数

//将顶点添加到顶点列表
void addVertex(char label) {
    struct Vertex* vertex = (struct Vertex*) malloc(sizeof(struct Vertex));
    vertex->label = label;
    vertex->visited = false;
    lstVertices[vertexCount++] = vertex;
}
//将边添加到边数组
void addEdge(int start,int end) {
    adjMatrix[start][end] = 1;
    adjMatrix[end][start] = 1;
}
//显示顶点
void displayVertex(int vertexIndex) {
    printf("%c ",lstVertices[vertexIndex]->label);
}
//获取相邻的未访问顶点
int getAdjUnvisitedVertex(int vertexIndex) {
   int i;
   for(i = 0; i < vertexCount; i++) {
      if(adjMatrix[vertexIndex][i] == 1 && lstVertices[i]->visited == false) {
         return i;
      }
   }
   return -1;
}
void depthFirstSearch() {
    int i;
    //将第一个节点标记为已访问
    lstVertices[0]->visited = true;
    //显示顶点
    displayVertex(0);
    //将顶点索引压入堆栈
    push(0);
   while(!isStackEmpty()) {
      //获取栈顶顶点的未访问顶点
      int unvisitedVertex = getAdjUnvisitedVertex(peek());
      //未找到相邻顶点
      if(unvisitedVertex == -1) {
         pop();
      } else {
         lstVertices[unvisitedVertex]->visited = true;
         displayVertex(unvisitedVertex);
         push(unvisitedVertex);
      }
   }
   //堆栈为空,搜索完成,重置访问标志    
   for(i = 0;i < vertexCount;i++) {
      lstVertices[i]->visited = false;
   }        
}
int main() {
   int i, j;

   for(i = 0; i < MAX; i++) {   // 设置邻接
      for(j = 0; j < MAX; j++) // 矩阵为 0
         adjMatrix[i][j] = 0;
   }
   addVertex('S');   // 0
   addVertex('A');   // 1
   addVertex('B');   // 2
   addVertex('C');   // 3
   addVertex('D');   // 4
   addEdge(0, 1);    // S - A
   addEdge(0, 2);    // S - B
   addEdge(0, 3);    // S - C
   addEdge(1, 4);    // A - D
   addEdge(2, 4);    // B - D
   addEdge(3, 4);    // C - D
   printf("Depth First Search: ");
   depthFirstSearch(); 
   return 0;   
}

输出

Depth First Search: S A D B C
//深度优先遍历的 C++ 代码
#include <iostream>
#include <array>
#include <vector>
constexpr int MAX = 5;
struct Vertex {
   char label;
   bool visited;
};
//堆栈变量
std::array<int, MAX> stack;
int top = -1;
//图变量
//顶点数组
std::array<Vertex*, MAX> lstVertices;
//邻接矩阵
std::array<std::array<int, MAX>, MAX> adjMatrix;
//顶点数量
int vertexCount = 0;
//堆栈函数
void push(int item) {
   stack[++top] = item;
}
int pop() {
   return stack[top--];
}
int peek() {
   return stack[top];
}
bool isStackEmpty() {
   return top == -1;
}
//图形函数
//将顶点添加到顶点列表
void addVertex(char label) {
   Vertex* vertex = new Vertex;
   vertex->label = label;
   vertex->visited = false;
   lstVertices[vertexCount++] = vertex;
}

//将边添加到边数组
void addEdge(int start, int end) {
    adjMatrix[start][end] = 1;
    adjMatrix[end][start] = 1;
}

//显示顶点
void displayVertex(int vertexIndex) {
    std::cout << lstVertices[vertexIndex]->label << " ";
}
//获取相邻的未访问顶点
int getAdjUnvisitedVertex(int vertexIndex) {
   for (int i = 0; i < vertexCount; i++) {
      if (adjMatrix[vertexIndex][i] == 1 && !lstVertices[i]->visited) {
         return i;
      }
   }
   return -1;
}
//标记第一个节点为已访问
void depthFirstSearch() {
   lstVertices[0]->visited = true;
   //显示顶点
   displayVertex(0);
   //将顶点索引压入堆栈
   push(0);
   while (!isStackEmpty()) {
       //获取栈顶顶点的未访问顶点
      int unvisitedVertex = getAdjUnvisitedVertex(peek());
      //未找到相邻顶点
      if (unvisitedVertex == -1) {
         pop();
      } else {
         lstVertices[unvisitedVertex]->visited = true;
         displayVertex(unvisitedVertex);
         push(unvisitedVertex);
      }
   }
   //堆栈为空,搜索完成,重置访问标志
   for (int i = 0; i < vertexCount; i++) {
      lstVertices[i]->visited = false;
   }
}
int main() {
   for (int i = 0; i < MAX; i++) {   //设置邻接
      for (int j = 0; j < MAX; j++) {    // 矩阵为 0
         adjMatrix[i][j] = 0;
      }
   }
   addVertex('S');
   addVertex('A');
   addVertex('B');
   addVertex('C');
   addVertex('D');
   addEdge(0, 1);
   addEdge(0, 2);
   addEdge(0, 3);
   addEdge(1, 4);
   addEdge(2, 4);
   addEdge(3, 4);
   std::cout << "Depth First Search: ";
   depthFirstSearch();
   return 0;
}

输出

Depth First Search: S A D B C
//深度优先遍历的Java程序
public class DepthFirstSearch {
    private static final int MAX = 5;
    private static class Vertex {
        char label;
        boolean visited;
    }
    private static int[] stack = new int[MAX];
    private static int top = -1;
    private static Vertex[] lstVertices = new Vertex[MAX];
    private static int[][] adjMatrix = new int[MAX][MAX];
    private static int vertexCount = 0;
    private static void push(int item) {
        stack[++top] = item;
    }
    private static int pop() {
        return stack[top--];
    }
    private static int peek() {
        return stack[top];
    }
    private static boolean isStackEmpty() {
        return top == -1;
    }
    private static void addVertex(char label) {
        Vertex vertex = new Vertex();
        vertex.label = label;
        vertex.visited = false;
        lstVertices[vertexCount++] = vertex;
    }
    private static void addEdge(int start, int end) {
        adjMatrix[start][end] = 1;
        adjMatrix[end][start] = 1;
    }
    private static void displayVertex(int vertexIndex) {
        System.out.print(lstVertices[vertexIndex].label + " ");
    }
    private static int getAdjUnvisitedVertex(int vertexIndex) {
        for (int i = 0; i < vertexCount; i++) {
            if (adjMatrix[vertexIndex][i] == 1 && !lstVertices[i].visited) {
                return i;
            }
        }
        return -1;
    }
    private static void depthFirstSearch() {
        lstVertices[0].visited = true;
        displayVertex(0);
        push(0);
        while (!isStackEmpty()) {
            int unvisitedVertex = getAdjUnvisitedVertex(peek());

            if (unvisitedVertex == -1) {
                pop();
            } else {
                lstVertices[unvisitedVertex].visited = true;
                displayVertex(unvisitedVertex);
                push(unvisitedVertex);
            }
        }
        for (int i = 0; i < vertexCount; i++) {
            lstVertices[i].visited = false;
        }
    }
    public static void main(String[] args) {
        for (int i = 0; i < MAX; i++) {
            for (int j = 0; j < MAX; j++) {
                adjMatrix[i][j] = 0;
            }
        }
        addVertex('S');   // 0
        addVertex('A');   // 1
        addVertex('B');   // 2
        addVertex('C');   // 3
        addVertex('D');   // 4
        addEdge(0, 1);    // S - A
        addEdge(0, 2);    // S - B
        addEdge(0, 3);    // S - C
        addEdge(1, 4);    // A - D
        addEdge(2, 4);    // B - D
        addEdge(3, 4);    // C - D
        System.out.print("Depth First Search: ");
        depthFirstSearch();
    }
}

输出

Depth First Search: S A D B C
#深度优先遍历的Python程序
MAX = 5
class Vertex:
    def __init__(self, label):
        self.label = label
        self.visited = False
#堆栈变量
stack = []
top = -1
#图变量
#顶点数组
lstVertices = [None] * MAX
#邻接矩阵
adjMatrix = [[0] * MAX for _ in range(MAX)]
#顶点数量
vertexCount = 0
#堆栈函数
def push(item):
    global top
    top += 1
    stack.append(item)
def pop():
    global top
    item = stack[top]
    del stack[top]
    top -= 1
    return item
def peek():
    return stack[top]
def isStackEmpty():
    return top == -1
#图函数
#将顶点添加到顶点列表
def addVertex(label):
    global vertexCount
    vertex = Vertex(label)
    lstVertices[vertexCount] = vertex
    vertexCount += 1
#将边添加到边数组
def addEdge(start, end):
    adjMatrix[start][end] = 1
    adjMatrix[end][start] = 1
#显示顶点
def displayVertex(vertexIndex):
    print(lstVertices[vertexIndex].label, end=' ')
def getAdjUnvisitedVertex(vertexIndex):
    for i in range(vertexCount):
        if adjMatrix[vertexIndex][i] == 1 and not lstVertices[i].visited:
            return i
    return -1
def depthFirstSearch():
    lstVertices[0].visited = True
    displayVertex(0)
    push(0)
    while not isStackEmpty():
        unvisitedVertex = getAdjUnvisitedVertex(peek())
        if unvisitedVertex == -1:
            pop()
        else:
            lstVertices[unvisitedVertex].visited = True
            displayVertex(unvisitedVertex)
            push(unvisitedVertex)
    for i in range(vertexCount):
        lstVertices[i].visited = False
for i in range(MAX):
    for j in range(MAX):
        adjMatrix[i][j] = 0
addVertex('S')   # 0
addVertex('A')   # 1
addVertex('B')   # 2
addVertex('C')   # 3
addVertex('D')   # 4
addEdge(0, 1)    # S - A
addEdge(0, 2)    # S - B
addEdge(0, 3)    # S - C
addEdge(1, 4)    # A - D
addEdge(2, 4)    # B - D
addEdge(3, 4)    # C - D
print("Depth First Search:", end=' ')
depthFirstSearch()

输出

Depth First Search: S A D B C

点击查看深度优先搜索 (BFS) 算法的 C 实现

DFS 算法的复杂度

时间复杂度

DFS 算法的时间复杂度表示为 O(V + E),其中 V 是节点数,E 是边数。

空间复杂度

DFS 算法的空间复杂度为 O(V)。