首页 > 其他分享 >JS Graph (图-数据结构)

JS Graph (图-数据结构)

时间:2024-04-04 09:23:50浏览次数:23  
标签:vet const Graph param JS v1 v2 adjList 数据结构

Code:

/**
 * 基于邻接表实现的无向图
 * @class
 */
class GraphAdjList {
    /**
     * @type {Map<any, any[]>}
     */
    adjList;

    /**
     * 构造函数
     * @constructor
     * @param {[any, any][]} edges 
     */
    constructor(edges) {
        this.adjList = new Map();
        /**
         * 初始化现有的顶点与边
         */
        for (const [e1, e2] of edges) {
            this.addVertex(e1);
            this.addVertex(e2);
            this.addEdge(e1, e2);
        }
    }

    /**
     * 获取顶点数量
     * @returns 
     */
    size() {
        return this.adjList.size;
    }

    /**
     * 添加顶点
     * @param vet 
     * @returns 
     */
    addVertex(vet) {
        //// 如果该顶点已经存在
        if (this.adjList.has(vet)) {
            return;
        }
        // 在邻接表中添加一个新链表
        this.adjList.set(vet, []);
    }

    /**
     * 删除顶点
     * @param vet 
     */
    removeVertex(vet) {
        if (!this.adjList.has(vet)) {
            throw new Error('Illegal Argument Exception');
        }
        // 删除该顶点所对应的链表
        this.adjList.delete(vet);
        // 删除其他顶点与该顶点形成的“边”
        const values = this.adjList.values();
        for (const arr of values) {
            const idx = arr.indexOf(vet);
            if (idx > -1) {
                arr.splice(idx, 1);
            }
        }
    }

    /**
     * 添加边
     * @param v1 
     * @param v2 
     */
    addEdge(v1, v2) {
        if (!this.adjList.has(v1) || !this.adjList.has(v2) || v1 === v2) {
            throw new Error('Illegal Argument Exception');
        }
        // 连接v1-v2,形成新的边
        this.adjList.get(v1).push(v2);
        this.adjList.get(v2).push(v1);
    }

    /**
     * 删除边
     * @param v1 
     * @param v2 
     */
    removeEdge(v1, v2) {
        if (!this.adjList.has(v1) || !this.adjList.has(v2) || v1 === v2) {
            throw new Error('Illegal Argument Exception');
        }
        const v1Idx = this.adjList.get(v2).indexOf(v1);
        const v2Idx = this.adjList.get(v1).indexOf(v2);
        this.adjList.get(v1).splice(v2Idx, 1);
        this.adjList.get(v2).splice(v1Idx, 1);
    }

    // 打印链表
    print() {
        console.log('邻接表 =');
        for (const [key, value] of this.adjList) {
            const valList = [];
            for (const piece of value) {
                valList.push(piece);
            }
            console.log(key + ':' + valList.toString());
        }
    }
}

 

/**
 * 基于邻接矩阵实现的无向图
 * @class
 */
class GraphAdjMat {
    /**
     * 顶点列表(元素代表顶点值,元素索引代表顶点索引)
     * @type {any[]}
     */
    vertices;
    /**
     * 邻接矩阵(行列索引代表顶点索引)
     * @type {any[][]}
     */
    adjMat;

    /**
     * 构造器
     * @constructor
     * @param {any[]} vertices 
     * @param {[number, number][]} edges 
     */
    constructor(vertices, edges) {
        this.vertices = [];
        this.adjMat = [];
        // 添加顶点
        for (const val of vertices) {
            this.addVertex(val);
        }
        // 添加边
        for (const [x, y] of edges) {
            this.addEdge(x, y);
        }
    }

    /**
     * 顶点数量
     * @returns 
     */
    size() {
        return this.vertices.length;
    }

    /**
     * 添加顶点
     * @param {any} val 
     */
    addVertex(val) {
        const n = this.size();
        this.vertices.push(val);
        // 添加行
        const newRow = [];
        for (let i = 0; i < n; i++) {
            newRow.push(0);
        }
        this.adjMat.push(newRow);
        // 添加列
        for (const row of this.adjMat) {
            row.push(0);
        }
    }

    /**
     * 删除顶点
     * @param {number} index 
     */
    removeVertex(index) {
        if (index >= this.size()) {
            throw new RangeError('Index Out Of Bounds Exception');
        }
        this.vertices.splice(index, 1);
        // 删除行
        this.adjMat.splice(index, 1);
        // 删除列
        for (const row of this.adjMat) {
            row.splice(index, 1);
        }
    }

    /**
     * 添加边
     * @param {number} i 
     * @param {number} j 
     */
    addEdge(i, j) {
        // 处理边界条件
        if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {
            throw new RangeError('Index Out Of Bounds Exception');
        }
        this.adjMat[i][j] = 1;
        this.adjMat[j][i] = 1;
    }

    /**
     * 删除边
     * @param {number} i 
     * @param {number} j 
     */
    removeEdge(i, j) {
        if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {
            throw new RangeError('Index Out Of Bounds Exception');
        }
        this.adjMat[i][j] = 0;
        this.adjMat[j][i] = 0;
    }
}

 

图的遍历操作

Code: 

function bfsGraph(graph, startVet) {
    const ans = [];
    const vis = new Set();
    vis.add(startVet);
    const q = [startVet];

    while (q.length > 0) {
        const vet = q.shift();
        ans.push(vet);
        const adjList = graph.adjList.get(vet) ?? []
        for (const adjVet of adjList) {
            if (vis.has(adjVet)) {
                continue;
            }
            q.push(adjVet);
            vis.add(adjVet);
        }
    }

    return ans;
}

 

标签:vet,const,Graph,param,JS,v1,v2,adjList,数据结构
From: https://www.cnblogs.com/fanqshun/p/18110479

相关文章

  • node.js启动http服务
    新建一个文件server.js,代码如下//导入http模块consthttp=require('http');//定义主机和端口号consthostname='127.0.0.1';constport=3000;//创建HTTP服务器constserver=http.createServer((req,res)=>{//获得HTTP请求的method和url:console.......
  • 30 天精通 RxJS (08):简易拖拉实作 - take, first, takeUntil, concatAll
    我们今天要接着讲take,first,takeUntil,concatAll这四个operators,并且实作一个简易的拖拉功能。Operatorstaketake是一个很简单的operator,顾名思义就是取前几个元素后就结束,范例如下varsource=Rx.Observable.interval(1000)varexample=source.take(3)example.......
  • 数据结构与算法
    1.1数据结构的研究内容程序=数据结构+算法  ———程序的本质 例1:图书管理系统操作对象:若干行数据记录操作算法:查询、插入、删除、修改等操作对象之间的关系:线性关系数据结构:线性数据结构、线性表例2:文件系统的结构图如图可以看到,这是一个典型的树型结构问题,数据......
  • 数据结构——从入门到入土
    链表的建立及遍历:分为如下几步:声明链表这种结构,比如:点击查看代码typedefstructnode*listlink;//定义一个指针类型名称,使指针变量能像其他变量那样声明,而不需要在每个指针变量前加*typedefstructnude(){intdata;structlistlinknext;}LNode;//声明......
  • 数据结构与算法分析实验3 [进阶]通过链表实现多项式加法和乘法
    文章目录大致内容介绍多项式加法代码一览头文件Poly.h内容如下:实现文件Poly.cpp内容如下:初始化增加元素删除元素功能函数遍历函数清除销毁打印多项式向多项式内插入一个元素源文件main.cpp内容如下:实现效果:多项式乘法实现方法:在Poly.h中添加声明:在Poly.cpp中添加实现:在......
  • nextjs 的函数,参数,属性装饰器的使用
    //属性装饰器constdoc1:PropertyDecorator=(target:any,val:string|symbol)=>{console.log(target);console.log(val);val="覆盖";}//方法装饰器constdoc2:MethodDecorator=(target:any,val:string|symbol,desc:any)=>{cons......
  • python 解析json字符串保存到对象中
    在Python中,你可以使用内置的json模块来解析JSON字符串并保存到对象中。以下是一个简单的示例:pythonimportjson#假设你有以下的JSON字符串json_string='{"name":"Alice","age":25,"city":"NewYork"}'#使用json模块的loads方法将JSON字符串解析为Python对象(在这种情况下......
  • 如何根据JSON文件内容生成自定义对象
    在Python中,你可以使用json模块来解析JSON文件,并将解析后的数据映射到自定义的Python对象上。这通常涉及到定义一个类,并为该类实现一个__init__方法来初始化对象的属性。然后,你可以编写一个函数来读取JSON文件,将解析后的数据传递给类的构造函数,从而创建自定义对象。下面是一个简单......
  • 数据结构——队列(包括循环队列)——Java版
    目录队列介绍:基本概念:应用:Java实现示例:循环队列的Java实现:队列介绍:队列(Queue)是一种常见的数据结构,它按照先进先出(FIFO,First-In-First-Out)的原则管理数据。在现实生活中,队列的概念很容易理解,就像是排队等待服务的人群一样。在计算机科学领域,队列同样扮演着重要的角色,在......
  • JS实现检查给定时间范围是否在每天的某个时间段内
    //解析时间字符串,返回对应的分钟数functionparseTime(timeStr){const[hours,minutes]=timeStr.split(':').map(num=>parseInt(num));returnhours*60+minutes;}//解析时间字符串,返回对应的Date对象functionparseTimeString(timeStr){const......