Javascript数据结构——图Graph

当然,让我们深入探讨一下JavaScript中的图数据结构,并列出一些常见的面试题及其代码示例。

图数据结构详解

图(Graph)是一种非线性的数据结构,由节点(也称为顶点)和连接这些节点的边组成。节点可以表示实体(如人、地点、事物等),而边则表示这些实体之间的关系。图可以分为有向图和无向图:

  • 有向图(Directed Graph):边有方向,即从一个节点指向另一个节点。
  • 无向图(Undirected Graph):边没有方向,表示两个节点之间的连接。
图的表示方法
  1. 邻接矩阵(Adjacency Matrix)

    • 使用一个二维数组表示,如果节点i和节点j之间有边,则数组[i][j]为1(或边的权重),否则为0。
    • 优点:查找边是否存在很快(O(1))。
    • 缺点:空间复杂度较高,尤其是稀疏图(边的数量远小于节点对数量的图)。
  2. 邻接表(Adjacency List)

    • 使用一个数组或链表数组表示,每个节点对应一个链表,链表中存储该节点连接的所有节点。
    • 优点:空间复杂度较低,适合稀疏图。
    • 缺点:查找边是否存在的时间复杂度较高(O(V))。
图的遍历
  1. 深度优先搜索(DFS, Depth-First Search)

    • 使用栈(递归或显式栈)遍历节点,尽可能深入搜索每一个分支。
    • 可以用递归或迭代实现。
  2. 广度优先搜索(BFS, Breadth-First Search)

    • 使用队列逐层遍历节点。
    • 常用于寻找最短路径(在无权图中)。

常见面试题及其代码

  1. 判断图是否有环(DFS)
function hasCycle(graph) {
    const visited = new Set();
    const recursionStack = new Set();

    function dfs(node) {
        if (recursionStack.has(node)) return true;
        if (visited.has(node)) return false;

        visited.add(node);
        recursionStack.add(node);

        for (const neighbor of graph[node] || []) {
            if (dfs(neighbor)) return true;
        }

        recursionStack.delete(node);
        return false;
    }

    for (const node in graph) {
        if (dfs(node)) return true;
    }

    return false;
}
  1. 图的深度优先遍历(DFS)
function dfsTraversal(graph, start, visited = new Set()) {
    if (visited.has(start)) return;
    visited.add(start);
    console.log(start);

    for (const neighbor of graph[start] || []) {
        dfsTraversal(graph, neighbor, visited);
    }
}
  1. 图的广度优先遍历(BFS)
function bfsTraversal(graph, start) {
    const queue = [start];
    const visited = new Set();

    while (queue.length > 0) {
        const node = queue.shift();
        if (!visited.has(node)) {
            visited.add(node);
            console.log(node);

            for (const neighbor of graph[node] || []) {
                if (!visited.has(neighbor)) {
                    queue.push(neighbor);
                }
            }
        }
    }
}
  1. 计算图的拓扑排序(Kahn’s Algorithm)
function topologicalSort(graph) {
    const inDegree = {};
    const result = [];
    const queue = [];

    // Initialize in-degree map
    for (const node in graph) {
        inDegree[node] = 0;
    }

    // Calculate in-degrees
    for (const node in graph) {
        for (const neighbor of graph[node] || []) {
            inDegree[neighbor] = (inDegree[neighbor] || 0) + 1;
        }
    }

    // Enqueue nodes with zero in-degree
    for (const node in inDegree) {
        if (inDegree[node] === 0) {
            queue.push(node);
        }
    }

    // Process nodes
    while (queue.length > 0) {
        const node = queue.shift();
        result.push(node);

        for (const neighbor of graph[node] || []) {
            inDegree[neighbor]--;
            if (inDegree[neighbor] === 0) {
                queue.push(neighbor);
            }
        }
    }

    // If there was a cycle, not all nodes would be visited
    return result.length === Object.keys(graph).length ? result : [];
}
  1. 计算所有节点对之间的最短路径(Floyd-Warshall Algorithm)
function floydWarshall(graph) {
    const n = Object.keys(graph).length;
    const dist = JSON.parse(JSON.stringify(graph));

    for (let k = 0; k < n; k++) {
        for (let i = 0; i < n; i++) {
            for (let j = 0; j < n; j++) {
                if (dist[i][k] !== Infinity && dist[k][j] !== Infinity && dist[i][k] + dist[k][j] < dist[i][j]) {
                    dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
    }

    return dist;
}
  1. 检测二分图(Bipartite Graph)
function isBipartite(graph) {
    const colors = {};
    const queue = [];

    function bfs(node, color) {
        colors[node] = color;
        queue.push(node);

        while (queue.length > 0) {
            const currentNode = queue.shift();
            const currentColor = colors[currentNode];

            for (const neighbor of graph[currentNode] || []) {
                if (!colors[neighbor]) {
                    colors[neighbor] = -currentColor;
                    queue.push(neighbor);
                } else if (colors[neighbor] === currentColor) {
                    return false;
                }
            }
        }

        return true;
    }

    for (const node in graph) {
        if (!colors[node]) {
            if (!bfs(node, 1)) {
                return false;
            }
        }
    }

    return true;
}
  1. 图的最小生成树(Prim’s Algorithm)
function primMST(graph) {
    const n = Object.keys(graph).length;
    const key = new Array(n).fill(Infinity);
    const parent = new Array(n).fill(-1);
    const inMST = new Array(n).fill(false);

    key[0] = 0;
    parent[0] = -1;

    for (let count = 0; count < n - 1; count++) {
        let u = -1, min = Infinity;

        for (let v = 0; v < n; v++) {
            if (!inMST[v] && key[v] < min) {
                u = v;
                min = key[v];
            }
        }

        inMST[u] = true;

        for (const v of graph[u] || []) {
            if (!inMST[v] && graph[u][v] < key[v]) {
                parent[v] = u;
                key[v] = graph[u][v];
            }
        }
    }

    // Construct MST
    const mst = [];
    for (let i = 1; i < n; i++) {
        mst.push([parent[i], i, graph[parent[i]][i]]);
    }

    return mst;
}
}

图的克鲁斯克尔算法(Kruskal’s Algorithm)

class UnionFind {
    constructor(n) {
        this.parent = new Array(n);
        for (let i = 0; i < n; i++) {
            this.parent[i] = i;
        }
    }

    find(u) {
        if (this.parent[u] !== u) {
            this.parent[u] = this.find(this.parent[u]); // 路径压缩,使得后续查找更快
        }
        return this.parent[u];
    }

    union(u, v) {
        let rootU = this.find(u);
        let rootV = this.find(v);
        if (rootU !== rootV) {
            this.parent[rootU] = rootV;
        }
    }
}

function kruskalMST(graph) {
    // 图的表示:graph = [ [u, v, weight], ... ]
    let edges = graph.slice().sort((a, b) => a[2] - b[2]); // 排序边
    let n = new Set(); // 存储所有顶点
    for (let edge of edges) {
        n.add(edge[0]);
        n.add(edge[1]);
    }
    let uf = new UnionFind(n.size);
    let mst = [];
    let mstCost = 0;

    for (let edge of edges) {
        let u = edge[0];
        let v = edge[1];
        let weight = edge[2];
        if (uf.find(u) !== uf.find(v)) {
            uf.union(u, v);
            mst.push(edge);
            mstCost += weight;
        }
    }

    return {
        mst: mst,
        cost: mstCost
    };
}

// 示例使用
let graph = [
    [0, 1, 10],
    [0, 2, 6],
    [0, 3, 5],
    [1, 3, 15],
    [2, 3, 4]
];

let result = kruskalMST(graph);
console.log("Edges in MST:", result.mst);
console.log("Total cost of MST:", result.cost);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/945638.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

各种 Amazon EBS 卷类型

Amazon Elastic Block Store&#xff08;EBS&#xff09;是 Amazon Web Services&#xff08;AWS&#xff09;提供的一项持久性块存储服务&#xff0c;它允许用户为 EC2 实例提供高效、可靠的存储。EBS 卷是 AWS 云环境中存储数据的基础组件&#xff0c;广泛应用于数据库、文件…

nvidia_gpu_exporter 显卡监控

导入 grafana/dashboard.json https://github.com/utkuozdemir/nvidia_gpu_exporter/blob/master/grafana/dashboard.json参考 nvidia_gpu_exporter

jvm排查问题-实践追踪问题 与思路--堆内堆外内存泄漏排查方针

概述 排查问题的一般思路是:现象 ——> 直接原因 ——>根本原因。 从问题现象出发,可以分为 应用逻辑问题、资源使用问题、虚拟机异常: 应用逻辑可能导致报错增加、死锁、程序退出等;资源问题主要集中在CPU上升和内存上升(OOM Kill);虚拟机问题通常包括GC问题、进…

CPT203 Software Engineering 软件工程 Pt.1 概论和软件过程(中英双语)

文章目录 1.Introduction1.1 What software engineering is and why it is important&#xff08;什么是软件工程&#xff0c;为什么它很重要&#xff09;1.1 We can’t run the modern world without software&#xff08;我们的世界离不开软件&#xff09;1.1.1 What is Soft…

【Java数据结构】LinkedList与链表

认识LinkedList LinkedList就是一个链表&#xff0c;它也是实现List接口的一个类。LinkedList就是通过next引用将所有的结点链接起来&#xff0c;所以不需要数组。LinkedList也是以泛型的方法实现的&#xff0c;所以使用这个类都需要实例化对象。 链表分为很多种&#xff0c;比…

从0入门自主空中机器人-2-2【无人机硬件选型-PX4篇】

1. 常用资料以及官方网站 无人机飞控PX4用户使用手册&#xff08;无人机基本设置、地面站使用教程、软硬件搭建等&#xff09;&#xff1a;https://docs.px4.io/main/en/ PX4固件开源地址&#xff1a;https://github.com/PX4/PX4-Autopilot 飞控硬件、数传模块、GPS、分电板等…

详解MySQL在Windows上的安装

目录 查看电脑上是否安装了MySQL 下载安装MySQL 打开MySQL官网&#xff0c;找到DOWNLOADS 然后往下翻&#xff0c;找到MySQL Community(GPL) Downloads>> 然后找到MySQL Community Server 然后下载&#xff0c;选择No thanks,just start my download. 然后双击进行…

【git】(一)在vscode上使用git进行版本控制(结合指令、含示例)

vscode中的git插件将git操作从git指令简化到简单的图形界面操作&#xff0c;不用再去记忆git指令&#xff0c;操作简单直观了很多。第一次使用时&#xff0c;为了加深理解&#xff0c;我将一些基本操作和该操作底层使用的命令结合起来&#xff0c;并包含实例&#xff0c;方便学…

安卓入门二 Kotlin基础

Kotlin Kotlin的历史 Kotlin由Jet Brains公司开发设计&#xff0c;2011年公布第一版&#xff0c;2012年开源。 2016年发布1.0正式版&#xff0c;并且Jet Brains在IDEA加入对Kotlin的支持&#xff0c;安卓自此又有新的选择。 2019年谷歌宣布Kotlin成为安卓第一开发语言&#x…

【MATLAB第111期】基于MATLAB的sobol全局敏感性分析方法二阶指数计算

【MATLAB第111期】基于MATLAB的sobol全局敏感性分析方法二阶指数计算 一、简介 在MATLAB中计算Sobol二阶效应指数通常涉及到全局敏感性分析&#xff08;Global Sensitivity Analysis, GSA&#xff09;&#xff0c;其中Sobol方法是一种流行的技术&#xff0c;用于评估模型输入…

线段树例题题解

卫星覆盖&#xff08;NOI1997&#xff09; 题面&#xff1a; SERCOI&#xff08;Space-Earth Resource Cover-Observe lnstitute&#xff09; 是一个致力于利用卫星技术对空间和地球资源进行覆盖观测的组织。现在他们研制成功一种新型资源观测卫星 -SERCOI-308。这种卫星可以…

FFmpeg 编码和解码

文章目录 音频格式AACADIF音频数据交换格式ADTS音频数据传输流 音频解码音频编码 视频格式H264GOP图像组I帧&#xff0c;P帧&#xff0c;B帧H264压缩技术H264压缩级别H264视频级别H264码流结构SPSPPS 解码视频编码视频 音频格式 AAC AAC全称 Advanced Audio Coding&#xff0…

vue 组件库二次封装

vue 组件库二次封装 需求背景&#xff1a;项目使用arco-design组件库&#xff0c;ui 界面对于单选有统一的界面&#xff0c; 对于封装组件有一个大原则就是我们应该尽量保持原有组件的接口&#xff0c;除了我们需要封装的功能外&#xff0c;我们不应该改变原有组件的接口&#…

Kafka 幂等性与事务

文章目录 幂等性实现机制配置使用局限性 事务使用场景配置使用实现机制事务过程事务初始化事务开始事务提交事务取消事务消费 幂等性 Producer 无论向 Broker 发送多少次重复的数据&#xff0c;Broker 端只会持久化一条&#xff0c;保证数据不丢失且不重复。 实现机制 通过引…

LVS 负载均衡原理 | 配置示例

注&#xff1a;本文为 “ LVS 负载均衡原理 | 配置” 相关文章合辑。 部分内容已过时&#xff0c;可以看看原理实现。 未整理去重。 使用 LVS 实现负载均衡原理及安装配置详解 posted on 2017-02-12 14:35 肖邦 linux 负载均衡集群是 load balance 集群的简写&#xff0c;翻…

CannotRetrieveUpdates alert in disconnected OCP 4 cluster解决

环境&#xff1a; Red Hat OpenShift Container Platform (RHOCP) 4 问题&#xff1a; Cluster Version Operator 不断发送警报&#xff0c;表示在受限网络/断开连接的 OCP 4 集群中无法接收更新。 在隔离的 OpenShift 4 集群中看到 CannotRetrieveUpdates 警报&#xff1a; …

详解从输入url到页面渲染

当你在浏览器中输入一个 URL 并按下回车键&#xff0c;浏览器会经历一系列步骤来加载并渲染页面。这些步骤包括 DNS 解析、缓存处理、建立连接、发送请求、接收响应、解析 HTML、构建 DOM 树和 CSSOM 树、执行 JavaScript、布局和绘制等。以下是这些步骤的详细解释&#xff0c;…

Linux(Centos 7.6)目录结构详解

Linux(Centos 7.6)是一个操作系统&#xff0c;其核心设计理念是将一切资源抽象为文件&#xff0c;即一切皆文件。比如系统中的硬件设备硬盘、网络接口等都被视为文件。Windows系统一般是分为C、D、E盘。而Linux(Centos 7.6)是以斜线"/"作为文件系统的开始目录&#x…

【蓝桥杯选拔赛真题85】python摆放箱子 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析

目录 python摆放箱子 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python摆放箱子 第十五届蓝桥杯青少年组python比赛选拔赛真题详细解析 一…

数据分析思维(六):分析方法——相关分析方法

数据分析并非只是简单的数据分析工具三板斧——Excel、SQL、Python&#xff0c;更重要的是数据分析思维。没有数据分析思维和业务知识&#xff0c;就算拿到一堆数据&#xff0c;也不知道如何下手。 推荐书本《数据分析思维——分析方法和业务知识》&#xff0c;本文内容就是提取…