图搜索算法详解

简介: 图搜索算法是用于在图结构中寻找特定节点或路径的算法。图是由节点(或顶点)和边组成的集合,节点代表对象,边代表节点之间的连接。图搜索算法广泛应用于各种领域,比如网络路由、社交媒体分析、推荐系统等。 V哥最近总是在多个地方都看到关于图搜索算法的讨论

图搜索算法是用于在图结构中寻找特定节点或路径的算法。图是由节点(或顶点)和边组成的集合,节点代表对象,边代表节点之间的连接。图搜索算法广泛应用于各种领域,比如网络路由、社交媒体分析、推荐系统等。 V哥最近总是在多个地方都看到关于图搜索算法的讨论,下面是一些常见的图搜索算法:

1. 深度优先搜索(DFS) 深度优先搜索是一种用于遍历或搜索树或图的算法。该算法会尽可能深地搜索图的分支。当节点v的所有边都已被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这个过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。

2. 广度优先搜索(BFS) 广度优先搜索是一种先遍历最近的节点,逐渐向外扩展的搜索算法。它从源节点开始,首先访问所有距离源节点为1的节点,然后访问所有距离源节点为2的节点,以此类推,直到访问到目标节点。广度优先搜索可以确保在找到最短路径时停止。

3. A搜索算法 A搜索算法是一种启发式搜索算法,它使用启发式函数来评估从源节点到目标节点的路径的成本。启发式函数是一种估计函数,它提供了从当前节点到目标节点的估计成本。A搜索算法在优先队列中根据f(n) = g(n) + h(n)的值来选择下一个要访问的节点,其中g(n)是从源节点到当前节点的实际成本,h(n)是当前节点到目标节点的估计成本。A搜索算法可以找到最短路径,但它的性能取决于启发式函数的选择。

4. Dijkstra算法 Dijkstra算法是一种用于在加权图中找到最短路径的算法。它从源节点开始,首先访问所有直接相邻的节点,然后访问所有距离源节点为2的节点,以此类推,直到访问到目标节点。与广度优先搜索不同,Dijkstra算法考虑了边的权重,因此它适用于加权图。

这些图搜索算法在计算机科学中非常重要,它们为解决各种问题提供了强大的工具。在实际应用中,选择合适的算法取决于具体问题的需求和图的结构特性。

以下是四种图搜索算法的详细介绍和Java代码实现案例。

1、深度优先搜索(DFS)

深度优先搜索(DFS)是一种用于遍历或搜索树或图的算法。DFS沿着一个分支遍历,直到这个分支的末端,然后进行回溯。

Java代码实现:

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class Graph {
   
    private int V; // 顶点的数量
    private List<List<Integer>> adj; // 邻接表

    public Graph(int v) {
   
        V = v;
        adj = new ArrayList<>(v);
        for (int i = 0; i < v; ++i) {
   
            adj.add(new ArrayList<>());
        }
    }

    public void addEdge(int v, int w) {
   
        adj.get(v).add(w); // 添加边
    }

    public void DFS(int v) {
   
        boolean[] visited = new boolean[V];
        Stack<Integer> stack = new Stack<>();

        stack.push(v);
        visited[v] = true;

        while (!stack.isEmpty()) {
   
            int vertex = stack.pop();
            System.out.print(vertex + " ");

            List<Integer> neighbors = adj.get(vertex);
            for (int neighbor : neighbors) {
   
                if (!visited[neighbor]) {
   
                    stack.push(neighbor);
                    visited[neighbor] = true;
                }
            }
        }
    }
}

2、广度优先搜索(BFS)

广度优先搜索(BFS)是一种先遍历最近的节点,逐渐向外扩展的搜索算法。BFS从源节点开始,首先访问所有距离源节点为1的节点,然后访问所有距离源节点为2的节点,以此类推,直到访问到目标节点。

Java代码实现:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class Graph {
   
    private int V; // 顶点的数量
    private List<List<Integer>> adj; // 邻接表

    public Graph(int v) {
   
        V = v;
        adj = new ArrayList<>(v);
        for (int i = 0; i < v; ++i) {
   
            adj.add(new ArrayList<>());
        }
    }

    public void addEdge(int v, int w) {
   
        adj.get(v).add(w); // 添加边
    }

    public void BFS(int v) {
   
        boolean[] visited = new boolean[V];
        Queue<Integer> queue = new LinkedList<>();

        visited[v] = true;
        queue.add(v);

        while (!queue.isEmpty()) {
   
            int vertex = queue.poll();
            System.out.print(vertex + " ");

            List<Integer> neighbors = adj.get(vertex);
            for (int neighbor : neighbors) {
   
                if (!visited[neighbor]) {
   
                    queue.add(neighbor);
                    visited[neighbor] = true;
                }
            }
        }
    }
}

3、A*搜索算法

A*搜索算法是一种启发式搜索算法,它使用启发式函数来评估从源节点到目标节点的路径的成本。A搜索算法在优先队列中根据f(n) = g(n) + h(n)的值来选择下一个要访问的节点,其中g(n)是从源节点到当前节点的实际成本,h(n)是当前节点到目标节点的估计成本。

Java代码实现:


import java.util.*;

public class AStarSearch {
   
    class Node {
   
        int id;
        int g; // 从起始点到当前点的成本
        int h; // 当前点到终点的估计成本
        int f; // g + h
        Node parent;

        public Node(int id, int g, int h, Node parent) {
   
            this.id = id;
            this.g = g;
            this.h = h;
            this.f = g + h;
            this.parent = parent;
        }
    }

    public List<Integer> aStarSearch(int start, int goal, int[][] graph) {
   
        PriorityQueue<Node> openList = new PriorityQueue<>(Comparator.comparingInt(node -> node.f));
        HashSet<Integer> closedList = new HashSet<>();

        Node startNode = new Node(start, 0, heuristic(start, goal), null);
        openList.add(startNode);

        while (!openList.isEmpty()) {
   
            Node currentNode = openList.poll();
            if (currentNode.id == goal) {
   
                return getPath(currentNode);
            }

            closedList.add(currentNode.id);
            for (int i = 0; i < graph[currentNode.id].length; i++) {
   
                if (graph[currentNode.id][i] != 0) {
   
                    int neighborId = i;
                    if (closedList.contains(neighborId)) {
   
                        continue;
                    }

                    int tentativeG = currentNode.g + graph[currentNode.id][i];
                    if (!openList.contains(new Node(neighborId, 0,

                    if (!openList.contains(new Node(neighborId, 0, 0, null)) || tentativeG < openList.contains(new Node(neighborId, 0, 0, null)).g) {
   
                        openList.add(new Node(neighborId, tentativeG, heuristic(neighborId, goal), currentNode));
                    }
                }
            }
        }
        return null;
    }

    private List<Integer> getPath(Node node) {
   
        List<Integer> path = new ArrayList<>();
        while (node != null) {
   
            path.add(0, node.id);
            node = node.parent;
        }
        return path;
    }

    private int heuristic(int current, int goal) {
   
        // 这里使用曼哈顿距离作为启发式函数
        return Math.abs(current - goal);
    }
}

4、Dijkstra算法

Dijkstra算法是一种用于在加权图中找到最短路径的算法。它从源节点开始,首先访问所有直接相邻的节点,然后访问所有距离源节点为2的节点,以此类推,直到访问到目标节点。与广度优先搜索不同,Dijkstra算法考虑了边的权重,因此它适用于加权图。

Java代码实现:

import java.util.*;

public class DijkstraAlgorithm {
   
    public void dijkstra(int graph[][], int src) {
   
        int V = graph.length;
        int dist[] = new int[V]; // 存储最短路径的数组
        Boolean sptSet[] = new Boolean[V]; // 标记节点是否被包括在最短路径树中

        // 初始化所有距离为无穷大,sptSet全部为false
        for (int i = 0; i < V; i++) {
   
            dist[i] = Integer.MAX_VALUE;
            sptSet[i] = false;
        }

        // 源节点到自己的距离为0
        dist[src] = 0;

        // 找到最短路径树中的所有节点
        for (int count = 0; count < V - 1; count++) {
   
            // 从未处理的节点中选择最小距离节点
            int u = minDistance(dist, sptSet);

            // 标记选中的节点为处理过
            sptSet[u] = true;

            // 更新与选中节点相邻的节点的距离
            for (int v = 0; v < V; v++) {
   
                if (!sptSet[v] && graph[u][v] != 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) {
   
                    dist[v] = dist[u] + graph[u][v];
                }
            }
        }

        // 打印最短路径数组
        printSolution(dist, V);
    }

    // 一个用来找到最小距离节点的函数
    private int minDistance(int dist[], Boolean sptSet[]) {
   
        int min = Integer.MAX_VALUE, minIndex = -1;
        for (int v = 0; v < dist.length; v++) {
   
            if (!sptSet[v] && dist[v] <= min) {
   
                min = dist[v];
                minIndex = v;
            }
        }
        return minIndex;
    }

    // 打印构造的最短路径树
    private void printSolution(int dist[], int n) {
   
        System.out.println("节点 \t\t 最短距离");
        for (int i = 0; i < n; i++) {
   
            System.out.println(i + " \t\t " + dist[i]);
        }
    }

    public static void main(String[] args) {
   
        DijkstraAlgorithm dijkstra = new DijkstraAlgorithm();
        int graph[][] = new int[][] {
   
            {
   0, 4, 0, 0, 0, 0, 0, 8, 0},
            {
   4, 0, 8, 0, 0, 0, 0, 11, 0},
            {
   0, 8, 0, 7, 0, 4, 0, 0, 2},
            {
   0, 0, 7, 0, 9, 14, 0, 0, 0},
            {
   0, 0, 0, 9, 0, 10, 0, 0, 0},
            {
   0, 0, 4, 14, 10, 0, 2, 0, 0},
            {
   0, 0, 0, 0, 0, 2, 0, 1, 6},
            {
   8, 11, 0, 0, 0, 0, 1, 0, 7},
            {
   0, 0, 2, 0, 0, 0, 6, 7, 0}
        };
        dijkstra.dijkstra(graph, 0);
    }
}

以上是四种图搜索算法的Java实现。每种算法都有其特定的应用场景:

  • DFS适用于探索所有可能的分支,例如游戏中的棋盘搜索、编译器中的语法分析等。
  • BFS适用于寻找最短路径,特别是在无权图中。
  • A*搜索算法适用于在有权图中寻找最短路径,特别是当图较大且目标节点较远时。
  • Dijkstra算法适用于在有权图中寻找最短路径,但不适用于有负权边的图。

在实际应用中,选择合适的算法取决于具体问题的需求和图的结构特性。这里 V哥必须要强调一下,如果图很大且目标节点很远,A*搜索算法可能是更好的选择,因为它使用启发式函数来指导搜索,从而减少搜索空间。如果图是无权的,或者权重相同,BFS将是一个简单且有效的选择。DFS则适用于需要探索所有可能性的情况。好了,以上就是 V哥关于图搜索算法的一些见解,分享给你,一起进步。

相关文章
|
3月前
|
算法
【算法】二分算法——搜索插入位置
【算法】二分算法——搜索插入位置
|
16天前
|
算法 搜索推荐 数据库
二分搜索:高效的查找算法
【10月更文挑战第29天】通过对二分搜索的深入研究和应用,我们可以不断挖掘其潜力,为各种复杂问题提供高效的解决方案。相信在未来的科技发展中,二分搜索将继续发挥着重要的作用,为我们的生活和工作带来更多的便利和创新。
24 1
|
1月前
|
算法 决策智能
基于禁忌搜索算法的VRP问题求解matlab仿真,带GUI界面,可设置参数
该程序基于禁忌搜索算法求解车辆路径问题(VRP),使用MATLAB2022a版本实现,并带有GUI界面。用户可通过界面设置参数并查看结果。禁忌搜索算法通过迭代改进当前解,并利用记忆机制避免陷入局部最优。程序包含初始化、定义邻域结构、设置禁忌列表等步骤,最终输出最优路径和相关数据图表。
|
2月前
|
大数据 UED 开发者
实战演练:利用Python的Trie树优化搜索算法,性能飙升不是梦!
在数据密集型应用中,高效搜索算法至关重要。Trie树(前缀树/字典树)通过优化字符串处理和搜索效率成为理想选择。本文通过Python实战演示Trie树构建与应用,显著提升搜索性能。Trie树利用公共前缀减少查询时间,支持快速插入、删除和搜索。以下为简单示例代码,展示如何构建及使用Trie树进行搜索与前缀匹配,适用于自动补全、拼写检查等场景,助力提升应用性能与用户体验。
56 2
|
1月前
|
存储 算法 C++
【搜索算法】 跳马问题(C/C++)
【搜索算法】 跳马问题(C/C++)
|
1月前
|
人工智能 算法 Java
【搜索算法】数字游戏(C/C++)
【搜索算法】数字游戏(C/C++)
|
3月前
|
机器学习/深度学习 算法 文件存储
【博士每天一篇文献-算法】 PNN网络启发的神经网络结构搜索算法Progressive neural architecture search
本文提出了一种名为渐进式神经架构搜索(Progressive Neural Architecture Search, PNAS)的方法,它使用顺序模型优化策略和替代模型来逐步搜索并优化卷积神经网络结构,从而提高了搜索效率并减少了训练成本。
55 9
|
3月前
|
算法
【算法】递归、搜索与回溯——汉诺塔
【算法】递归、搜索与回溯——汉诺塔
|
3月前
|
存储 算法 调度
基于和声搜索算法(Harmony Search,HS)的机器设备工作最优调度方案求解matlab仿真
通过和声搜索算法(HS)实现多机器并行工作调度,以最小化任务完成时间。在MATLAB2022a环境下,不仅输出了工作调度甘特图,还展示了算法适应度值的收敛曲线。HS算法模拟音乐家即兴创作过程,随机生成初始解(和声库),并通过选择、微调生成新解,不断迭代直至获得最优调度方案。参数包括和声库大小、记忆考虑率、音调微调率及带宽。编码策略将任务与设备分配映射为和声,目标是最小化完成时间,同时确保满足各种约束条件。
|
4月前
|
数据采集 算法 JavaScript
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
JavaScript字符串搜索涵盖`indexOf`、`includes`及KMP算法。`indexOf`返回子字符串位置,`includes`检查是否包含子字符串。KMP是高效的搜索算法,尤其适合长模式匹配。示例展示了如何在数据采集(如网页爬虫)中使用这些方法,结合代理IP进行安全搜索。代码示例中,搜索百度新闻结果并检测是否含有特定字符串。学习这些技术能提升编程效率和性能。
119 1
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法