无厘头 Graph

媒介

本日晚上无意翻到一个图的文章,查了一下觉得网上完成和其他都好庞杂,所以本身按明白搞了一下,不知道是我完成是不是是错了…觉得还好~进入正题,先照样来点理论知识,不过大多是本身的主意,不一定都对,可以改正。内容泉源来自《JavaScript 数据构造和算法》。

图是一种数学模子,和数学挂勾平常都邑比较庞杂,所以笼统的明白成最简朴的模子,点-线 模子。实在最简朴的是 1 个点的模子,触及 2 个点还好,3 个点事后模子就会作出响应的转变。

这里用简朴的言语来讲图中的二元关联,不过照样先假定一点数学标记:

G => 示意一切的极点鸠合

V => 示意极点

E => 示意边,笼统意义上是无向边

那末用数学来示意就是:G=<V, E>

实在基础不必明白数学的模子,我这里明白是只须要知道这是一个点-线模子就可以了。

怎样示意图呢?

这里有两种示意要领:表和矩阵,其间都是毗邻关联

这里我有一个测试图,在网上弄的,虽然是无向图,实在在我们代码中,肯定是有向的,是进口的题目:

《无厘头 Graph》

图的构造肯定事后,就可以做出表的构造了,这里我没有用方向,由于我明白的图是一个不能简朴示意的,明白成坐标系更好明白一点。分为:x, y 轴的体式格局。个中,x0 示意最先,背面示意相邻的点,按顺时针分列(不一定按这个递次)。

《无厘头 Graph》

代码中的图

在代码中示意,没有图形那末直观,所以须要映射成代码模子,这里简朴完成一下,然则不具备许多功用。

假定:

class G => 一个图的类,包含图的定义和经常使用遍历要领

this.V => 示意点鸠合的个数,然则这里我舍弃了 0 的位置

this.T => 我按数据库表的体式格局明白定名的,关联的鸠合

this.E => 边的个数

this.visited => 访问过的 bool 鸠合,实在就是标记

this.defined => 东西小函数,是不是定义过,与图无关

所以末了有关的标记有:

G、V、T、E

是不是是觉得一会儿变简朴了,不过顺序的笼统有一个上层,那就是类。
然后我这里按计算机的体式格局,定义了输入、输出函数:input、output

class G {
    constructor(V) {
        this.V = V;
        this.T = [];
        this.E = 0;
        this.visited = [];

        for (let v = 0; v < this.V; ++v) {
            this.T[v] = [];
            this.T[v].push(-1);
        }

        this.defined = s => s !== void 0;
    }
    input(v, w) {
        this.T[v].push(w);
        this.T[w].push(v);

        this.E++;

        return this;
    }
    output() {
        console.table(this.T);
    }
}

然后可以看出,实在边是由点的衔接构成的,恰好相符数学的定义,而且与相邻有相关性。

那末,完成了构造,还应该有其他作用,那末接下来看一下遍历算法:深度遍历(DFS) 和 广度遍历(BFS)。正确来讲应该是优先采纳什么战略的遍历体式格局。实在我这里的完成觉得…不好,和树关联大了点,不过树的大鸠合就可以上升到图。

dfs(v) {
    this.visited[v] = true;

    if (this.defined( this.T[v] )) {
        console.log('老孙到此一游:' + v);
    }

    this.T[v].forEach(t => {
        if (t !== -1 && !this.visited[t]) {
            this.dfs(t);
        }
    });
}

关于深度遍历,是将图按一个牢固方向,纵向的效果,所以是一个递归的构造。

bfs(node) {
    this.visited[node] = true;

    var queue = [];
    queue.push(node);
    while(queue.length > 0) {
        var v = queue.shift();
        if(this.defined( this.T[v] )) {
            console.log('老孙到此一游:' + v);
        }

        this.T[v].forEach(t => {
            if(t !== -1 && !this.visited[t]) {
                this.visited[t] = true;
                queue.push(t);
            }
        });
    }
}

关于广度遍历,是将图按一个牢固方向,横向的效果,所以是一个链式收支的关联,这里是用行列,在 JS 中做行列这类先进先出比较简朴。

// 测试代码
var v = [1, 2, 3, 4, 5];
let g = new G( v.length + 1 );
g.input(1, 2).input(1, 5)
    .input(2, 4).input(2, 5).input(2, 3)
    .input(3, 4)
    .input(4, 5)
    .output();
g.dfs(1);
console.log('------------');
// 让它失忆一下
g.visited = [];
g.bfs(1);

《无厘头 Graph》

……-_-# 简朴玩一下,睡觉了 zZZ

    原文作者:小撸
    原文地址: https://segmentfault.com/a/1190000007696453
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞