数据结构-图论

在计算机科学中,一个图就是一些顶点的集合,这些顶点通过一系列边结对(连接)。顶点用圆圈表示,边就是这些圆圈之间的连线。顶点之间通过边连接。

注意:顶点有时也称为节点或者交点,边有时也称为链接

主要研究的目的是 事物之间的关系, 顶点代表事物,边代表两个事物之间的关系

以下图栗子


image.png

image.png

image.png

图通常的特点

  • 一组顶点: 通常用V(Vertex)表示顶点的集合
  • 一组边: 通常用E(Edge)表示边的集合
    • 边是顶点之间的连线
    • 边可以是有向的,也可以是无向的
    • 比如: A---B,通常表示无向。 A-->B通常表示有向

图的术语

  • 顶点
  • 相邻顶点: 由一条边连接在一起的顶点称为相邻顶点
  • 度:一个顶点的度是相邻顶点的数量
  • 路径: 顶点v1,v2....vn的一个连续序列
    • 简单路径: 简单路径要求不包含重复的顶点
    • 回路: 第一个顶点和最后一个顶点相同的路径
  • 无向图: 所有的边都没有方向
  • 有向图: 图中的边是有方向的
  • 无权图: 边没有携带权重
  • 有权图:边有一定的权重(表示你希望的数据:如花费的时间更少)

图的表示

一种比较常见的便是图的方式:

邻接矩阵

  • 邻接矩阵让 每个节点 和 一个整数 相 关联, 该整数作为数组的 下标值。
  • 我们用一个数组来表示顶点之间的连接


    image.png

解析

  • 在二维数组中 , 0表示没有连线,1表示有连线
    *通过二维数组,我们可以很快找到一个顶点和哪些顶点有连线

邻接矩阵的问题
如果图是一个稀疏图, 那么矩阵中将存在大量的0,浪费存储空间来表示不存在的边。

另一种表示图的方式

邻接表

邻接表由图中每个顶点以及和顶点相邻的顶点列表组成
这个列表有很多方式来储存:数组、链表、字典(哈希表)都可以

image.png

图解析:
比如我们要表示和 A顶点有关联的顶点(边), A和B,C,D有边
那么我们可以通过A找到对应的数组/链表/字典,取出其中的内容。

邻接表问题
邻接表计算“出度”是比较简单的(出度:指向别人的数量,入度:指向自己的数量)
邻接表如果要计算有向图的“入度”,是非常麻烦的事情,必须构造一个“逆邻接表”

图的遍历算法

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

两种算法思想

  • BFS: 基于队列,入队列的顶点先被探索
  • DFS:基于栈或使用递归, 通过将顶点存入栈中,顶点沿着路径被探索,存在新的相邻顶点就去访问

为了记录顶点访问状态,用三种颜色来表示

  • 白色: 该顶点没有被访问过
  • 灰色: 顶点被访问过,但是没有被探索过
  • 黑色: 顶点被访问过且被探索过。
image.png
image.png

代码实现




dict.js

// 创建字典的构造函数
function Dictionay() {
    // 字典属性
    this.items = {}

    // 字典操作方法
    // 在字典中添加键值对
    Dictionay.prototype.set = function (key, value) {
        this.items[key] = value
    }

    // 判断字典中是否有某个key
    Dictionay.prototype.has = function (key) {
        return this.items.hasOwnProperty(key)
    }

    // 从字典中移除元素
    Dictionay.prototype.remove = function (key) {
        // 1.判断字典中是否有这个key
        if (!this.has(key)) return false

        // 2.从字典中删除key
        delete this.items[key]
        return true
    }

    // 根据key去获取value
    Dictionay.prototype.get = function (key) {
        return this.has(key) ? this.items[key] : undefined
    }

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

    // 获取所有的value
    Dictionay.prototype.values = function () {
        return Object.values(this.items)
    }

    // size方法
    Dictionay.prototype.size = function () {
        return this.keys().length
    }

    // clear方法
    Dictionay.prototype.clear = function () {
        this.items = {}
    }
}

queue.js

// 自定义队列
function Queue() {
    var items = []

    // 队列操作的方法
    // enter queue方法
    this.enqueue = function (element) {
        items.push(element)
    }

    // delete queue方法
    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
    }
}

你可能感兴趣的:(数据结构-图论)