首页 > 其他分享 >Map Navigation System (Graph Algorithm)

Map Navigation System (Graph Algorithm)

时间:2025-01-07 19:34:54浏览次数:11  
标签:Map weight get int 复杂度 System new Navigation 节点

1.实验目的

为了更好地理解图数据结构,例如最短路径算法和最小生成树算法。

2.实验代码思路及算法复杂度分析

Graph类:记录图的顶点,边等信息

//GraphNode
record GraphNode(int v, double weight) {
}
​
//Edge
record GraphEdge(int s, int d, double weight) {
}
​
public class Graph {
    protected static final int NODE_COUNT = 26;
    private final List<List<GraphNode>> adjacencyList = new ArrayList<>();
    private final double[][] adjacencyMatrix;
​
    public Graph() {
        for (int i = 0; i < NODE_COUNT; i++) {
            adjacencyList.addLast(new ArrayList<>());     //初始化邻接链表
        }
​
        adjacencyMatrix = new double[NODE_COUNT][NODE_COUNT];
        for (int i = 0; i < NODE_COUNT; i++) {
            Arrays.fill(adjacencyMatrix[i], Double.MAX_VALUE);
            adjacencyMatrix[i][i] = 0; // Distance to self is 0
        }
    }
​
    //添加边
    public void addEdge(int start, int end, double weight) {
        adjacencyList.get(start).add(new GraphNode(end, weight));
        adjacencyList.get(end).add(new GraphNode(start, weight));
        adjacencyMatrix[start][end] = weight;
        adjacencyMatrix[end][start] = weight;
    }
}

记录路径信息函数collectPaths: collectPaths 方法通过前驱节点信息递归地构建最短路径,在最坏情况下,可能需要遍历图中的大部分节点来构建完整路径,其时间复杂度取决于图的结构和最短路径的分布情况,其时间复杂度为 O(V),因为最多也就是遍历所有节点一次来构建路径。

 //路径信息
    private void collectPaths(ArrayList<ArrayList<Integer>> record, int temp, int next, int x, Deque<Integer> stack, double weight, List<String> paths) {
        //向前寻找路径信息
        while (record.get(temp).getFirst() != x) {
            if (temp < 0 || temp >= NODE_COUNT) {
                return;
            }
            int m = record.get(temp).size();
            if (m > 1) { //如果在同一级中有多个节点,就复制相关信息进入递归
                for (int i = 1; i < m; i++) {
                    int v = record.get(temp).get(i);
                    Deque<Integer> newStack = new LinkedList<>(stack);
                    newStack.push(v);
                    collectPaths(record, v, v, x, newStack, weight + adjacencyMatrix[v][next], paths);
                }
            }
            int v = record.get(temp).getFirst();
            if (v < 0 || v >= NODE_COUNT) {
                break;
            }
            stack.push(v);
            temp = v;
            weight += adjacencyMatrix[temp][next];
            next = temp;
        }
        weight += adjacencyMatrix[x][next];
​
        StringBuilder path = new StringBuilder();
        path.append((char) (x + 'A'));
        while (!stack.isEmpty()) {
            int index = stack.pop();
            path.append("->").append((char) ('A' + index));
        }
        path.append("\n最短距离为 ").append(String.format("%.2f", weight)).append(" km.\n");
        paths.add(path.toString());
    }

(1) Given two locations, show the shortest path from one to the other on the map and its length.

功能一:采用Dijkstra与Bellman-Ford算法。

操作代码如下:

button1.setOnAction(event -> {
            outputArea.clear();
            outputArea.appendText("Operation 1:\n");
            String start = location1.getText();
            String end = location2.getText();
            if (start.length() == 1 && end.length() == 1 &&
                    (start.charAt(0) >= 'A' && start.charAt(0) <= 'Z') &&
                    (end.charAt(0) >= 'A' && end.charAt(0) <= 'Z')) {
                outputArea.appendText("Following is Dijkstra Alogorithm.\n");
                // 使用Dijkstra算法求两点间最短路径
                List<String> resultD = graph.findShortestPathDijkstra(start.charAt(0), end.charAt(0));
                StringBuilder s = new StringBuilder();
                for (int i = 0; i < resultD.size() - 1; i++) {
                    s.append(resultD.get(i));
                }
                s.append(resultD.get(resultD.size() - 1));
                outputArea.appendText("从 " + start + " 到 " + end + " 路线: " + s.toString() + "\n");
                outputArea.appendText("\nFollowing is Bellman-Ford Alogorithm.\n");
                // 使用Bellman-Ford算法求两点间最短路径(作为另一种解法示例,可按需选用或扩展更多算法对比)
                List<String> resultBF = graph.findShortestPathBellmanFord(start.charAt(0), end.charAt(0));
                StringBuilder s2 = new StringBuilder();
                for (int i = 0; i < resultD.size() - 1; i++) {
                    s2.append(resultBF.get(i));
                }
                s2.append(resultBF.get(resultBF.size() - 1));
                outputArea.appendText("从 " + start + " 到 " + end + " 路线: " + s2.toString() + "\n");
            } else {
                outputArea.appendText("输入地点错误,请重新输入。\n");
            }
        });
Dijkstra算法:
  //Dijkstra算法 单源最短路径
    public List<String> findShortestPathDijkstra(char s, char d) {
        int start = s - 'A', end = d - 'A';
        double[] distance = new double[NODE_COUNT];  //距离
        ArrayList<ArrayList<Integer>> lists = new ArrayList<>();  //记录前一个节点
        for (int i = 0; i < NODE_COUNT; i++) {
            ArrayList<Integer> list = new ArrayList<>();
            list.add(-1); // 初始化
            lists.add(list);
        }
        boolean[] visited = new boolean[NODE_COUNT];  //记录是否已经访问过了
​
        Arrays.fill(distance, Integer.MAX_VALUE);
        distance[start] = 0;
​
        PriorityQueue<Integer> heap = new PriorityQueue<>(Comparator.comparingDouble(a -> distance[a])); //最小堆
        heap.add(start);
​
        while (!heap.isEmpty()) {
            int index = heap.poll();
            if (visited[index]) continue;
            visited[index] = true;
            int l = adjacencyList.get(index).size();
            for (int i = 0; i < l; i++) {
                int ver = adjacencyList.get(index).get(i).v();      //提取相邻的节点信息
                double weight = adjacencyList.get(index).get(i).weight();
​
                if (visited[ver]) continue;
​
                if (distance[index] + weight < distance[ver]) {
                    distance[ver] = distance[index] + weight;
                    lists.remove(ver);
                    ArrayList<Integer> al = new ArrayList<>();
                    al.add(index);
                    lists.add(ver, al);
                    heap.add(ver);
                } else if (!visited[ver] && distance[index] + weight == distance[ver]) {
                    if (lists.get(ver).getFirst() == -1) {
                        lists.get(ver).removeFirst();
                        lists.get(ver).add(index);
                    } else {
                        lists.get(ver).add(index);
                    }
                }
            }
        }
        Deque<Integer> stack = new LinkedList<>();
        stack.add(end);
        List<String> paths = new ArrayList<>();
        collectPaths(lists, end, end, start, stack, 0, paths);
        return paths;
    }
时间复杂度分析:
  1. 初始化

    • 初始化 lists 用于记录前驱节点,时间复杂度为O(V)。

    • 初始化 visited ,d数组,时间复杂度为O(V)。

  2. 优先队列的初始化

    • 使用最小堆(即 PriorityQueue)来存储未访问的节点,初始时间复杂度为O(log⁡V)。

  3. 主循环和更新

    • 外层循环执行,直到 heap 为空。最坏情况下,如果图是稀疏的,Dijkstra 将会遍历所有的节点,即V次。

在每次迭代中,主要操作包括:

  • heap 中取出一个节点,时间复杂度为O(logV)。

  • 更新相邻节点的距离:

    • 对每个相邻节点,检查是否被访问,如果没有,则更新距离和前驱节点,这个相邻节点的处理可能会遍历所有与该节点相邻的边。

假设 E 是图中的边数,对于每个节点,最坏情况下,可能会遍历所有边,时间复杂度在这一部分是O(E*logV)。

综上所述:

稀疏图(

标签:Map,weight,get,int,复杂度,System,new,Navigation,节点
From: https://blog.csdn.net/2401_84974736/article/details/144991742

相关文章

  • System data
    什么是SDBSDB是系统数据块,它是硬件组态完成后,执行菜单“编译并保存”,如果没有错误,将产生实际硬件组态的系统数据块(即自动生成系统SDB)。SDB的类型SDB包含的内容硬件组态的相关信息SDB的作用硬件组态完成(包括网络组态)执行编译后产生系统数据块的好处是:如果没有系统数......
  • Systemd日志管理服务:Journald以及重要配置选项
    Journald是systemd引入的用于收集和存储日志数据的系统服务。它试图使系统管理员可以在越来越多的日志消息中更轻松地找到有趣且相关的信息。为了实现此目标,日记中的主要更改之一是用为日志消息优化的特殊文件格式替换简单的纯文本日志文件。这种文件格式使系统管理员可以更有效地......
  • Java 8系列之重新认识HashMap15
     摘要HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型。随着JDK(JavaDevelopmetKit)版本的更新,JDK1.8对HashMap底层的实现进行了优化,例如引入红黑树的数据结构和扩容的优化等。本文结合JDK1.7和JDK1.8的区别,深入探讨HashMap的结构实现和功能原理。简介Ja......
  • Java 8系列之重新认识HashMap12
    摘要HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型。随着JDK(JavaDevelopmetKit)版本的更新,JDK1.8对HashMap底层的实现进行了优化,例如引入红黑树的数据结构和扩容的优化等。本文结合JDK1.7和JDK1.8的区别,深入探讨HashMap的结构实现和功能原理。简介Java......
  • Java 8系列之重新认识HashMap2
    摘要HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型。随着JDK(JavaDevelopmetKit)版本的更新,JDK1.8对HashMap底层的实现进行了优化,例如引入红黑树的数据结构和扩容的优化等。本文结合JDK1.7和JDK1.8的区别,深入探讨HashMap的结构实现和功能原理。简介Java......
  • js WeakMap 作用和使用
    WeakMap是JavaScript中的一种键值对集合,类似于Map,但它有一些独特的特性,特别是关于其键的引用方式。WeakMap的键只能是对象,并且这些键是以弱引用的方式持有的。这意味着如果一个对象只被WeakMap引用而没有其他强引用,那么这个对象可能会在任何时候被垃圾回收。因此,WeakMap适......
  • designing scalable e-commerce trading systems
    <thinking>LetmeanalyzethekeycomponentsofKuaishou'se-commercesystembasedonthearticle:Keyarchitecturestoimplement:1.High-performanceinventorysystem(Redis+MySQL)2.Distributedtransactionhandlingfororders3.Dependencyman......
  • Map中经常被忽略但又非常好用的方法
    1.简介map是我们日常开发中常会的集合类之一,但是我们除了常用的get和put之外,其他的方法好像很少会用到,接下来我们就介绍一下几个经常被忽略但又很好用的方法.2.QuickStart2.1数据准备创建一个map对象,并声明几个用于测试的user对象Map<Integer,User>hashMap=Map......
  • Android13编译错误FAILED: SYSTEM_BUILD/out/target/product/qssi_au/system/vendor
    前言全局说明FAILED:SYSTEM_BUILD/out/target/product/qssi_au/system/vendorQSSI:notenabledforqssi_autargetas/release/QSSI/QSSI_enforced_targets_list.txtwasnotfound.YoucannotinstallfilestoSYSTEM_BUILD/out/target/product/qssi_au/system/vendorw......
  • js数组实例方法-lastIndexOf,join,keys,map
    Array.prototype.lastIndexOf()lastIndexOf()方法返回数组中给定元素最后一次出现的索引,如果不存在则返回-1。该方法从fromIndex开始向前搜索数组语法lastIndexOf(searchElement)lastIndexOf(searchElement,fromIndex)参数searchElement:被查找的元素fromIndex:以......