1. 程式人生 > 其它 >JS 資料結構 圖

JS 資料結構 圖

目的
  • 事物之間的關係

    頂點:事物[通常用 V(Vertex)表示頂點的集合]
    邊:兩個事物間的關係[通常用 E(Edge)表示邊的集合]

    • 邊是頂點和頂點之間的連線
    • 邊是有向的(A --> B),也可以是無向的(A – B)
  • 無權圖
    無權圖

  • 帶權圖
    帶權圖

程式碼實現:

class Graph {
  constructor() {
    this.vertexes = [] /* 頂點 */
    this.edges = new Dictionary() /* 邊 */
  }

  // 1. 新增頂點方法
  addVertex(vertex) {
    this.vertexes.push
(vertex) this.edges.set(vertex, []) } // 2. 新增邊方法(無向圖) addEdge(v1, v2) { this.edges.get(v1).push(v2) this.edges.get(v2).push(v1) } // 3. 初始化顏色 initializeColor() { let colors = {} for (const vertex of this.vertexes) { colors[vertex] = 'white' } return colors }
// toString方法 toString() { let resultString = '' // 遍歷所有的頂點以及頂點對應的邊 for (const v of this.vertexes) { resultString += v + ' -> ' for (const e of this.edges.get(v)) { resultString += e + ' ' } resultString += '\n' } return resultString } }
遍歷
  • 每個頂點訪問一遍,並且不能重複訪問
  • 兩種方法(都需要指定第一個訪問的頂點)
    • 廣度優先搜尋(BFS)
      [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-ZsgeMPzP-1621139698296)(<src/圖-廣度優先搜尋(BFS)].png>)
    • 深度優先搜尋(DFS)
  • 用三種顏色表示狀態
    • 白色:頂點還沒有被訪問
    • 灰色:頂點被訪問過,但並未被探索過
    • 黑色:頂點被訪問過且被完全探索過

廣度優先搜尋

bfs (initV, handler) {
    /* 1. 初始化顏色 */
    let colors = this.initializeColor()

    /* 2. 建立佇列 */
    let queue = new Queue()

    /* 3. 將頂點加入到佇列中 */
    queue.enqueue(initV)

    /* 4. 迴圈從佇列中取出元素 */
    while (!queue.isEmpty()) {
      /* 4.1 從佇列中取出一個頂點 */
      let vertex = queue.dequeue()

      /* 4.2 獲取和頂點相連的另外頂點 */
      let vList = this.edges.get(vertex)

      /* 4.3 將v的顏色設定成灰色 */
      colors[vertex] = 'gray'

      /* 4.4 遍歷所有的頂點,並且加入佇列中 */
      for (const node of vList) {
        if (colors[node] == 'white') {
          colors[node] = 'gray'
          queue.enqueue(node)
        }
      }

      /* 4.5 訪問頂點 */
      handler(vertex)

      /* 4.6 將頂點設定為黑色 */
      colors[vertex] = 'black'
    }
  }

深度優先搜尋

  dfs (initV, handler) {
    /* 1. 初始化顏色 */
    let colors = this.initializeColor()

    /* 2. 從某個節點開始遞迴訪問 */
    this.dfsOrder(initV, colors, handler)
  }
  /* 深度遞迴方法 */
  dfsOrder (v, colors, handler) {
    /* 1. 將顏色設定成灰色 */
    colors[v] = 'gray'

    /* 2. 處理v節點 */
    handler(v)

    /* 3. 訪問v相連的頂點 */
    let vList = this.edges.get(v)
    for (const node of vList) {
      if (colors[node] == 'white') {
        this.dfsOrder(node, colors, handler)
      }
    }
  }