美文网首页
学习js数据结构与算法7—图

学习js数据结构与算法7—图

作者: 陈左夕 | 来源:发表于2018-03-22 17:26 被阅读0次

    利用 字典
    function Map() {
        var items = {};
    
        // has(key)方法
        this.has = function (key) {
            return items.hasOwnProperty(key);
        };
        // set(key, val)方法
        this.set = function (key, val) {
            items[key] = val;
        };
    
        // remove(key)方法
        this.remove = function (key) {
            if (this.has(key)) {
                delete items[key];
                return true;
            }
            return false;
        };
        // get(key)方法
        this.get = function (key) {
            return this.has(key) ? items[key] : undefined;
        };
        // values()方法
        this.values = function () {
            return Object.values(items);
        };
        // keys()方法
        this.keys = function () {
            return Object.keys(items);
        };
        // clear()方法
        this.clear = function () {
            items = {};
        };
        // size()方法
        this.size = function () {
            return Object.keys(items).length;
        };
        // getItems()方法
        this.getItems = function () {
            return items;
        };
    }
    // 利用 队列
    function Queue() {
        // 使用数据结构为数组来存储队列中的元素
        var items = [];
        
        this.enqueue = function (ele) {
            items.push(ele);
        };
        this.dequeue = function () {
            return items.shift();
        };
        this.front = function () {
            return items[0];
        };
        this.isEmpty = function () {
            return items.length === 0;
        };
        this.size = function () {
            return items.length;
        };
        this.print = function () {
            console.log(items.toString());
        };
    }
    // 利用 栈
    function Stack() {
        var items = [];
        // push方法
        this.push = function(ele) {
            items.push(ele);    
        };
        // pop方法
        this.pop = function() {
            return items.pop();  
        };
        // peek方法
        this.peek = function() {
            return items[items.length - 1];  
        };
        // isEmpty方法
        this.isEmpty = function() {
            return items.length === 0;  
        };
        // clear方法
        this.clear = function() {
            // items.length = 0;  // 保留了数组其他属性
            items = [];     // 更高效
        };
        // size方法
        this.size = function() {
            return items.length;
        };
        
        // 最后实现一个辅助方法print打印栈的内容
        this.print = function() {
            console.log(items.toString());  
        };
    }
    创建图类
    function Graph() {
        var vertices = [];
        var adjList = new Map();
    
        this.addVertex = function (v) {
            vertices.push(v);
            adjList.set(v, []);
        };
    
        this.addEdge = function (v, w) {
            adjList.get(v).push(w);
            adjList.get(w).push(v);
        };
    
        // 输出
        this.toString = function () {
            var s = '';
            for (var i = 0; i < vertices.length; i++) {
                s += vertices[i] + ' -> ';
                var neighbors = adjList.get(vertices[i]);
                for (var j = 0; j < neighbors.length; j++) {
                    s += neighbors[j] + ' ';
                }
                s += '\n';
            }
            return s;
        };
    }
    
    var graph = new Graph();
    var myVertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
    for (var i = 0; i < myVertices.length; i++) {
        graph.addVertex(myVertices[i]);
    }
    
    graph.addEdge('A', 'B');
    graph.addEdge('A', 'C');
    graph.addEdge('A', 'D');
    graph.addEdge('C', 'D');
    graph.addEdge('C', 'G');
    graph.addEdge('D', 'G');
    graph.addEdge('D', 'H');
    graph.addEdge('B', 'E');
    graph.addEdge('B', 'F');
    graph.addEdge('E', 'I');
    
    console.log(graph.toString());
    // 使用广度优先搜索
    function printNode(val) {
        console.log('访问顶点:' + val);
    }
    // graph.bfs(myVertices[0], printNode);
    var shortestPathA = graph.BFS(myVertices[0]);
    console.log(shortestPathA);
    
    var fromVertex = myVertices[0];
    for (var i = 1; i < myVertices.length; i++) {
        var toVertex = myVertices[i],
            path = new Stack();
    
        for (var v = toVertex; v !== fromVertex; v = shortestPathA.predecessors[v]) {
            path.push(v);
        }
        path.push(fromVertex);
        var s = path.pop();
        while (!path.isEmpty()) {
            s += ' - ' + path.pop();
        }
        console.log(s);
    }
    // 使用深度优先搜索
    graph.dfs(printNode);

图的遍历

两种算法可以对图进行遍历:==广度优先搜索和深度优先搜索==

算法 数据结构
广度优先搜索
深度优先搜索 队列

当要标注已经访问过的顶点时,我们用三种颜色来反映它们的状态

  • 白色:表示该顶点还没有被访问。
  • 灰色:表示该顶点被访问过,但没有被搜索过。
  • 黑色:表示该顶点被访问过且被完全搜索过。
    // 初始化为白色状态
    var initColor = function () {
        var color = [];
        for (var i = 0; i < vertices.length; i++) {
            color[vertices[i]] = 'white'; //1
        }
        return color;
    };
    // 广度优先搜索
    this.bfs = function (v, callback) {
        var color = initColor(), //2
        queue = new Queue(); //3
        queue.enqueue(v); //4
        while (!queue.isEmpty()) {
            var u = queue.dequeue(), //6
            neighbors = adjList.get(u); //7
            color[u] = 'grey'; //8
            for (var i = 0; i < neighbors.length; i++) {
                var w = neighbors[i]; //10
                if (color[w] === 'white') {
                    color[w] = 'grey'; //12
                    queue.enqueue(w); //13
                }
            }
            color[u] = 'black'; //14
            callback && callback(u); //15
        }
    };
    this.BFS = function (v) {
        var color = initColor(), queue = new Queue(), d = [], //1
        pred = []; //2
        queue.enqueue(v);
        for (var i = 0; i < vertices.length; i++) {
            d[vertices[i]] = 0; // 4
            pred[vertices[i]] = null; //5
        }
        while (!queue.isEmpty()) {
            var u = queue.dequeue(), neighbors = adjList.get(u);
            color[u] = 'grey';
            for (var i = 0; i < neighbors.length; i++) {
                var w = neighbors[i];
                if (color[w] === 'white') {
                    color[w] = 'grey';
                    d[w] = d[u] + 1; // 6
                    pred[w] = u;
                    queue.enqueue(w);
                }
            }
            color[u] = 'black';
        }
        return {
            distances: d,
            predecessors: pred
        };
    };
    // 深度优先搜索
    this.dfs = function (callback) {
        var color = initColor();

        for (var i = 0; i < vertices.length; i++) {
            if (color[vertices[i]] === 'white') {
                dfsVisit(vertices[i], color, callback);
            }
        }
    };
    var dfsVisit = function (u, color, cb) {
        color[u] = 'grey';
        cb && cb(u);
        var neighbors = adjList.get(u);

        for (var i = 0; i < neighbors.length; i++) {
            var w = neighbors[i];
            if (color[w] === 'white') {
                dfsVisit(w, color, cb);
            }
        }
        color[u] = 'black';
    };
    // 改进版
    var time = 0;
    this.DFS = function () {
        var color = initColor(),
            d = [],
            f = [],
            p = [];

        time = 0;

        for (var i = 0; i < vertices.length; i++) {
            f[vertices[i]] = 0;
            d[vertices[i]] = 0;
            p[vertices[i]] = null;
        }

        for (i = 0; i < vertices.length; i++) {
            if (color[vertices[i]] === 'white') {
                DFSVisit(vertices[i], color, d, f, p);
            }
        }
        return {
            discovery: d,
            finished: f,
            predecessors: p
        };
    };

    var DFSVisit = function (u, color, d, f, p) {
        console.log('发现' + u);
        color[u] = 'grey';
        d[u] = ++time;
        var neighbors = adjList.get(u);

        for (var i = 0; i < neighbors.length; i++) {
            var w = neighbors[i];
            if (color[w] === 'white') {
                p[w] = u;
                DFSVisit(w, color, d, f, p);
            }
        }
        color[u] = 'black';
        f[u] = ++time;
        console.log('探索' + u);
    };

相关文章

网友评论

      本文标题:学习js数据结构与算法7—图

      本文链接:https://www.haomeiwen.com/subject/xftzqftx.html