JavaScript 数据结构与算法(四)图论

本文参考文献:https://www.cnblogs.com/AhuntSun-blog/p/12636718.html
配套视频教程:https://www.bilibili.com/video/BV1r7411n7Pw?p=1&spm_id_from=pageDriver

数据结构-四

图论 graph

简介

什么是图?

  • 图结构是一种与树结构有些相似的数据结构;
  • 图论是数学的一个分支,并且,在数学中,树是图的一种;
  • 图论以图为研究对象,研究顶点和边组成的图形的数学理论和方法;
  • 主要的研究目的为:事物之间的联系,顶点代表事物,边代表两个事物间的关系;

图的特点

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

在这里插入图片描述

图的常用术语

  • 顶点vertex:表示图中的一个节点 1,2,3;
  • edge:表示顶点和顶点之间的连线;
  • 相邻顶点:由一条边连接在一起的顶点称为相邻顶点,1的相邻顶点有2,3,5,6;
  • 度:一个顶点的度是相邻顶点的数量;
  • 路径path
    • 简单路径shortest path:一条从一个顶点到另一个顶点的路径,其中不包含重复的顶点,如1到4的路径:1 -> 5 -> 4;
    • 回路loop:第一个顶点和最后一个顶点相同的路径称为回路,如:1 -> 3 -> 5 -> 1;
  • 无向图undirected graph:图中的所有边都是没有方向的;
  • 有向图directed graph:图中的所有边都是有方向的;
  • 无权图``:无权图中的边没有任何权重意义;
  • 带权图:带权图中的边有一定的权重含义;
图的表示方式

邻接矩阵
这是一种常用的图的表示方式:

  • 可以使用二维数组来表示邻接矩阵;
  • 邻接矩阵让每个节点和一个整数相关联,该整数作为数组的下标值;
  • 使用一个二维数组来表示顶点之间的连接;

在这里插入图片描述
如上图所示,这是一个无向图:

  • 二维数组中的0表示没有连线,1表示有连线;
  • 如:A[0][3] = 1,表示A和D之间有连接;
  • 邻接矩阵的对角线上的值都为0,表示A - A ,B - B,等自回路都没有连接(自己与自己之间没有连接);
  • 若为无向图,则邻接矩阵应为对角线上元素全为0的对称矩阵;

邻接矩阵存在的问题

  • 如果图是一个稀疏图,那么邻接矩阵中将存在大量的 0,造成存储空间的浪费

邻接表

  • 邻接表由图中每个顶点以及和顶点相邻的顶点列表组成;
  • 这个列表可用多种方式存储,比如:数组/链表/字典(哈希表等都可以;
    在这里插入图片描述

如上图所示:

  • 图中可清楚看到A与B、C、D相邻,假如要表示这些与A顶点相邻的顶点(边),可以通过将它们作为A的值(value)存入到对应的数组/链表/字典中。
  • 之后,通过键(key)A可以十分方便地取出对应的数据;

邻接表的问题

  • 邻接表可以容易地 获得出度,即某一顶点指向其他顶点的个数
  • 但是,邻接表计算入度指向某一顶点的其他顶点的个数称为该顶点的入度)十分困难。此时需要构造逆邻接表才能有效计算入度;
  • 在实际应用中,入度使用较多,出度使用较少,因此本文采用邻接表实现graph图;
封装与实现

本文采用邻接表的方式来表示边 edge,用字典类(自行封装实现的 来存储邻接表,实现的图为无向无权图

添加字典类 & 队列类

由于之后要用到字典类和队列类,先对这两个数据结构进行封装:

//封装字典类
function Dictionary(){
   
  //字典属性
  this.items = {
   }

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

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

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

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

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

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

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

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

// -------------------------------------
// 基于数组封装队列类
function Queue() {
   
	// 属性
	this.items = []

// 方法
// 1.将元素加入到队列中
Queue.prototype.enqueue = element => {
   
  this.items.push(element)
}

// 2.从队列中删除前端元素
Queue.prototype.dequeue = () => {
   
  return this.items.shift()
}

// 3.查看前端的元素
Queue.prototype.front = () => {
   
  return this.items[0]
}

// 4.查看队列是否为空
Queue.prototype.isEmpty = () => {
   
  return this.items.length == 0;
}

// 5.查看队列
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值