js資料結構--圖(graph)

遨翔在知識的海洋裡發表於2019-01-18

圖(graph)

js資料結構--圖(graph)

js資料結構--圖(graph)

js資料結構--圖(graph)

實現鄰接表

實際圖

js資料結構--圖(graph)

graph.js

var Graph = function() {
    //儲存頂點
    var vertices = []
        //邊
    var adjList = {}
        //新增頂點
    this.addVertices = function(v) {
            vertices.push(v)
            adjList[v] = []
        }
        // 新增邊
    this.addEdge = function(a, b) {
        adjList[a].push(b)
        adjList[b].push(a)
    }
    this.print = function() {
        var s = '\n';
        for (var i = 0; i < vertices.length; i++) {
            var dingdian = vertices[i]
            s += dingdian + '=>'
            var bian = adjList[dingdian]
            for (var j = 0; j < bian.length; j++) {
                s += bian[j]
            }
            s += '\n'
        }
        console.log(s)
    }
}

var g = new Graph()
g.addVertices('A')
g.addVertices('B')
g.addVertices('C')
g.addVertices('D')
g.addVertices('E')
g.addVertices('F')


g.addEdge('A', 'B')
g.addEdge('A', 'C')
g.addEdge('A', 'D')
g.addEdge('B', 'E')
g.addEdge('B', 'F')
g.addEdge('C', 'D')
g.print()
複製程式碼

例項化

js資料結構--圖(graph)

廣度優先

var Queue = function() {
    var items = [];
    //入隊
    this.enqueue = function(el) {
            items.push(el)
        }
        //出隊
    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;
    }
}

var Graph = function() {
    //儲存頂點
    var vertices = []
        //邊
    var adjList = {}
        //新增頂點
    this.addVertices = function(v) {
            vertices.push(v)
            adjList[v] = []
        }
        // 新增邊
    this.addEdge = function(a, b) {
        adjList[a].push(b)
        adjList[b].push(a)
    }

    //white  未發現
    //gray   已發現未探索
    //black  已探索
    var initColor = function() {
        var color = {}
        for (var i = 0; i < vertices.length; i++) {
            color[vertices[i]] = 'white'
        }
        return color
    }

    this.bfs = function(v, callback) {
        var color = initColor()

        var queue = new Queue()
        queue.enqueue(v)
        while (!queue.isEmpty()) {
            var now = queue.dequeue()
            var bian = adjList[now]
            for (var i = 0; i < bian.length; i++) {
                var w = bian[i]
                if (color[w] === 'white') {
                    color[w] = 'gray'
                    queue.enqueue(w)
                }
            }
            color[now] = 'black'
            if (callback) {
                callback(now)
            }
        }
    }
}

var g = new Graph()
g.addVertices('A')
g.addVertices('B')
g.addVertices('C')
g.addVertices('D')
g.addVertices('E')
g.addVertices('F')


g.addEdge('A', 'B')
g.addEdge('A', 'C')
g.addEdge('A', 'D')
g.addEdge('B', 'E')
g.addEdge('B', 'F')
g.addEdge('C', 'D')

複製程式碼

例項化

js資料結構--圖(graph)

最短路徑: 廣度優先

記錄,回溯路徑

var Queue = function() {
    var items = [];
    //入隊
    this.enqueue = function(el) {
            items.push(el)
        }
        //出隊
    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;
    }
}

var Graph = function() {
    //儲存頂點
    var vertices = []
        //邊
    var adjList = {}
        //新增頂點
    this.addVertices = function(v) {
            vertices.push(v)
            adjList[v] = []
        }
        // 新增邊
    this.addEdge = function(a, b) {
        adjList[a].push(b)
        adjList[b].push(a)
    }
    this.print = function() {
        var s = '\n';
        for (var i = 0; i < vertices.length; i++) {
            var dingdian = vertices[i]
            s += dingdian + '=>'
            var bian = adjList[dingdian]
            for (var j = 0; j < bian.length; j++) {
                s += bian[j]
            }
            s += '\n'
        }
        console.log(s)
    }

    //white  未發現
    //gray   已發現未探索
    //black  已探索
    var initColor = function() {
        var color = {}
        for (var i = 0; i < vertices.length; i++) {
            color[vertices[i]] = 'white'
        }
        return color
    }

    this.bfs = function(v, callback) {
        var color = initColor()

        var queue = new Queue()
        queue.enqueue(v)


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

        while (!queue.isEmpty()) {
            var now = queue.dequeue()
            var bian = adjList[now]
            for (var i = 0; i < bian.length; i++) {
                var w = bian[i]
                if (color[w] === 'white') {
                    color[w] = 'gray'

                    //設定回點
                    pred[w] = now
                    d[w] = d[now] + 1
                    queue.enqueue(w)
                }
            }
            color[now] = 'black'
            if (callback) {
                callback(now)
            }
        }

        return {
            pred: pred,
            d: d
        }
    }
}

var g = new Graph()
g.addVertices('A')
g.addVertices('B')
g.addVertices('C')
g.addVertices('D')
g.addVertices('E')
g.addVertices('F')


g.addEdge('A', 'B')
g.addEdge('A', 'C')
g.addEdge('A', 'D')
g.addEdge('B', 'E')
g.addEdge('B', 'F')
g.addEdge('C', 'D')

複製程式碼

例項化

js資料結構--圖(graph)

程式碼實現A-F的最短路徑

js資料結構--圖(graph)

var Queue = function() {
    var items = [];
    //入隊
    this.enqueue = function(el) {
            items.push(el)
        }
        //出隊
    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;
    }
}

var Graph = function() {
    //儲存頂點
    var vertices = []
        //邊
    var adjList = {}
        //新增頂點
    this.addVertices = function(v) {
            vertices.push(v)
            adjList[v] = []
        }
        // 新增邊
    this.addEdge = function(a, b) {
        adjList[a].push(b)
        adjList[b].push(a)
    }
    this.print = function() {
        var s = '\n';
        for (var i = 0; i < vertices.length; i++) {
            var dingdian = vertices[i]
            s += dingdian + '=>'
            var bian = adjList[dingdian]
            for (var j = 0; j < bian.length; j++) {
                s += bian[j]
            }
            s += '\n'
        }
        console.log(s)
    }

    //white  未發現
    //gray   已發現未探索
    //black  已探索
    var initColor = function() {
        var color = {}
        for (var i = 0; i < vertices.length; i++) {
            color[vertices[i]] = 'white'
        }
        return color
    }

    this.bfs = function(v, callback) {
        var color = initColor()

        var queue = new Queue()
        queue.enqueue(v)


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

        while (!queue.isEmpty()) {
            var now = queue.dequeue()
            var bian = adjList[now]
            for (var i = 0; i < bian.length; i++) {
                var w = bian[i]
                if (color[w] === 'white') {
                    color[w] = 'gray'

                    //設定回點
                    pred[w] = now
                    d[w] = d[now] + 1
                    queue.enqueue(w)
                }
            }
            color[now] = 'black'
            if (callback) {
                callback(now)
            }
        }

        return {
            pred: pred,
            d: d
        }
    }
}

var g = new Graph()
g.addVertices('A')
g.addVertices('B')
g.addVertices('C')
g.addVertices('D')
g.addVertices('E')
g.addVertices('F')


g.addEdge('A', 'B')
g.addEdge('A', 'C')
g.addEdge('A', 'D')
g.addEdge('B', 'E')
g.addEdge('B', 'F')
g.addEdge('C', 'D')
    // g.print()

g.addEdge('D', 'F')

var s = g.bfs("A")
var zuiduan = function(from, to) {
    var v = to; //設定當前點
    while (v != from) {
        console.log(v)
        v = s.pred[v]
    }
    console.log(v)
}

zuiduan("A", "F")
複製程式碼

例項化

js資料結構--圖(graph)

利用棧(Stack)優化列印順序

var Stack = function() {
    var items = [];
    // this.items = [];
    this.push = function(val) {
        items.push(val)
    }
    this.pop = function() {
        return items.pop()
    }
    this.peek = function() {
        return items[items.length - 1]
    }
    this.isEmpty = function() {
        return items.length === 0
    }
    this.size = function() {
        return items.length
    }
    this.clear = function() {
        items = []
    }
}

//省略

var s = g.bfs("A")
var zuiduan = function(from, to) {
    var v = to; //設定當前點
    var path = new Stack()
    while (v != from) {
        path.push(v)
        v = s.pred[v]
    }
    path.push(v)
    var str = ''
    while (!path.isEmpty()) {
        str += path.pop() + &emsp;'-'
    }
    str = str.slice(0, str.length - 1)
    console.log(str)
}

zuiduan("A", "F")


複製程式碼

js資料結構--圖(graph)

最短路徑: 深度優先

    //深度優先
    var dfsVisite = function(u, color, callback) {
        color[u] = 'gray'
        var n = adjList[u]
        for (var i = 0; i < n.length; i++) {
            var w = n[i]
            if (color[w] === 'white') {
                dfsVisite(w, color, callback)
            }
        }
        color[u] = 'black'
        if (callback) {
            callback(u)
        }
    }
    this.dfs = function(v, callback) {
        var color = initColor()
        dfsVisite(v, color, callback)
    }
複製程式碼

例項化

js資料結構--圖(graph)

相關文章