JS实现图

实现队列

function Queue() {
    this.items = []

    Queue.prototype.enqueue = function (ele) {
        this.items.push(ele);
    }

    Queue.prototype.dequeue = function () {
        return this.items.shift();
    }

    Queue.prototype.front = function () {
        return this.items[0];
    }

    Queue.prototype.isEmpty = function () {
        return this.items.length == 0;
    }

    Queue.prototype.size = function () {
        return this.items.length;
    }

    Queue.prototype.toString = function () {
        var resultStr = '';
        for (var i = 0; i < this.items.length; i++) {
            resultStr += this.items[i];
        }
        return resultStr;
    }
}

module.exports = Queue;

实现字典

function Dictionary() {
    this.items = {};

    this.set = function (key, value) {
        return this.items[key] = value;
    }

    this.has = function (key) {
        return this.items.hasOwnProperty(key);
    }

    this.remove = function (keu) {
        if (this.has(key)) {
            delete this.items[key];
            return true;
        }
        return false;
    }

    this.get = function (key) {
        return this.has(key) ? this.items[key] : undefined;
    }

    // 获取所有keys
    this.keys = function () {
        return Object.keys(this.items);
    }

    //获取所有values
    this.values = function () {
        return Object.values(this.items);
    }

    this.size = function () {
        return Object.keys(this.items).length;
    }

    this.clear = function () {
        this.items = {};
    }

    this.getItems = function () {
        return this.items;
    }
}

module.exports = Dictionary;

图的遍历

  • 广度优先搜索(Breadth-First Search,BFS
  • 深度优先搜索(Depth-First Search,DFS
  • 两个遍历算法,都需要明确指定第一个被访问的顶点

记录状态

白色:表示该顶点还没有被访问

灰色:表示该顶点被访问过,但并未探索过

黑色:表示该顶点被访问过且完全探索过

const Dict = require("./dict")
var print = console.log;

function Graph() {
    // 顶点
    this.vertices = [];
    // 边
    this.edges = new Dict();
    Graph.prototype.addVertex = function (v) {
        this.vertices.push(v);
        this.edges.set(v, []);
    }
    Graph.prototype.addEdge = function (v1, v2) {
        this.edges.get(v1).push(v2);
        this.edges.get(v2).push(v1);
    }
    Graph.prototype.toString = function () {
        var resultStr = "";
        for (var i = 0; i < this.vertices.length; i++) {
            resultStr += this.vertices[i] + "->"
            var vEdges = this.edges.get(this.vertices[i]);
            for (var j = 0; j < vEdges.length; j++) {
                resultStr += vEdges[j] + " ";
            }
            resultStr += "\n";
        }
        return resultStr
    }
}

var g = new Graph();
var myVertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
for (var i = 0; i < myVertices.length; i++) {
    g.addVertex(myVertices[i]);
}

g.addEdge('A', 'B');
g.addEdge('A', 'C');
g.addEdge('A', 'D');
g.addEdge('C', 'D');
g.addEdge('C', 'G');
g.addEdge('D', 'G');
g.addEdge('D', 'H');
g.addEdge('B', 'E');
g.addEdge('B', 'F');
g.addEdge('E', 'I');
print(g.edges);

广度 优先搜索

  • 广度优先算法从指定的第一个顶点开始遍历图,先访问其所有的相邻接点,就像一次访问图的一层
  • 先宽后深的访问顶点

BFS

    // 广度优先搜索(BFS)
    Graph.prototype.bfs = function (initV, handler) {
        // 1.初始化颜色
        var color = this.initializeColor();
        // 2.创建队列
        var queue = new Queue();
        // 3.将顶点加入队列中
        queue.enqueue(initV);
        // 4.循环从队列中取出元素
        while (!queue.isEmpty()) {
            // 4.1.从队列取出一个顶点
            var v = queue.dequeue();
            // 4.2.获取顶点和相连的另外顶点
            var vList = this.edges.get(v);
            // 4.3.将v的颜色设置灰色
            color[v] = 'gray';
            // 4.4.遍历所有的顶点,并且加入到队列中
            for (var i = 0; i < vList.length; i++) {
                var e = vList[i];
                if (color[e] == 'white') {
                    color[e] = 'gray';
                    queue.enqueue(e);
                }
            }
            // 4.5.v已经被探测,并且返回
            handler(v);
            // 4.6.将顶点设置为黑色
            color[v] = 'black';
        }
    //
    }
}
var result = '';
g.bfs(g.vertices[0], function (v) {
    result += v + ' ';
})
print(result) // A B C D E F G H I

深度 优先搜索

  • 深度优先搜索算法会从第一个指定的顶点开始遍历图,沿着路径知道这条路径最后被访问了
  • 接着原路回退并探索一条路径

DFS

    // 深度优先搜索(DFS)
    Graph.prototype.dfs = function (initV, handler) {
        // 1.初始化颜色
        var color = this.initializeColor();
        // 2.从某个顶点开始依次递归访问
        this.dfsVisit(initV, color, handler);
    }
    Graph.prototype.dfsVisit = function (v, color, handler) {
        // 1.将颜色设置为灰色
        color[v] = 'gray';
        // 2.处理v顶点
        handler(v);
        // 3.访问v相连的顶点
        var vList = this.edges.get(v);
        for (var i = 0; i < vList.length; i++) {
            var e = vList[i];
            if (color[e] == 'white') {
                this.dfsVisit(e, color, handler);
            }
        }
        // 4.将v设置为黑色
        color[v] = 'black';
    }
var result = '';
g.dfs(g.vertices[0], function (v) {
    result += v + ' ';
})
print(result); // A B E I F C D G H

总代码

const Dict = require('./dict');
const Queue = require('./queue');
var print = console.log;

function Graph() {
    // 顶点
    this.vertices = [];
    // 边
    this.edges = new Dict();
    Graph.prototype.addVertex = function (v) {
        this.vertices.push(v);
        this.edges.set(v, []);
    }
    Graph.prototype.addEdge = function (v1, v2) {
        this.edges.get(v1).push(v2);
        this.edges.get(v2).push(v1);
    }
    Graph.prototype.toString = function () {
        var resultStr = '';
        for (var i = 0; i < this.vertices.length; i++) {
            resultStr += this.vertices[i] + '->'
            var vEdges = this.edges.get(this.vertices[i]);
            for (var j = 0; j < vEdges.length; j++) {
                resultStr += vEdges[j] + ' ';
            }
            resultStr += '\n';
        }
        return resultStr
    }
    // 初始化状态颜色
    Graph.prototype.initializeColor = function () {
        var colors = [];
        for (var i = 0; i < this.vertices.length; i++) {
            colors[this.vertices[i]] = 'white';
        }
        return colors
    }
    // 广度优先搜索(BFS)
    Graph.prototype.bfs = function (initV, handler) {
        // 1.初始化颜色
        var color = this.initializeColor();
        // 2.创建队列
        var queue = new Queue();
        // 3.将顶点加入队列中
        queue.enqueue(initV);
        // 4.循环从队列中取出元素
        while (!queue.isEmpty()) {
            // 4.1.从队列取出一个顶点
            var v = queue.dequeue();
            // 4.2.获取顶点和相连的另外顶点
            var vList = this.edges.get(v);
            // 4.3.将v的颜色设置灰色
            color[v] = 'gray';
            // 4.4.遍历所有的顶点,并且加入到队列中
            for (var i = 0; i < vList.length; i++) {
                var e = vList[i];
                if (color[e] == 'white') {
                    color[e] = 'gray';
                    queue.enqueue(e);
                }
            }
            // 4.5.v已经被探测,并且返回
            handler(v);
            // 4.6.将顶点设置为黑色
            color[v] = 'black';
        }
    }
    // 深度优先搜索(DFS)
    Graph.prototype.dfs = function (initV, handler) {
        // 1.初始化颜色
        var color = this.initializeColor();
        // 2.从某个顶点开始依次递归访问
        this.dfsVisit(initV, color, handler);
    }
    Graph.prototype.dfsVisit = function (v, color, handler) {
        // 1.将颜色设置为灰色
        color[v] = 'gray';
        // 2.处理v顶点
        handler(v);
        // 3.访问v相连的顶点
        var vList = this.edges.get(v);
        for (var i = 0; i < vList.length; i++) {
            var e = vList[i];
            if (color[e] == 'white') {
                this.dfsVisit(e, color, handler);
            }
        }
        // 4.将v设置为黑色
        color[v] = 'black';
    }
}

var g = new Graph();
var myVertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
for (var i = 0; i < myVertices.length; i++) {
    g.addVertex(myVertices[i]);
}

g.addEdge('A', 'B');
g.addEdge('A', 'C');
g.addEdge('A', 'D');
g.addEdge('C', 'D');
g.addEdge('C', 'G');
g.addEdge('D', 'G');
g.addEdge('D', 'H');
g.addEdge('B', 'E');
g.addEdge('B', 'F');
g.addEdge('E', 'I');
print(g.edges.items);
var result = '';
g.bfs(g.vertices[0], function (v) {
    result += v + ' ';
})
print(result);
var result = '';
g.dfs(g.vertices[0], function (v) {
    result += v + ' ';
})
print(result);

输出:

输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值