数据结构
图论
- 图是网络结构的抽象模型, 是一组由边连接的节点
- 顶点:顶点是图中的节点,
- 边:边是连接顶点之间的连线
- 相邻顶点:由一条边相连的两个顶点
- 度:一个顶点的度是相邻顶点的个数
- 路径:路径是一个顶点到另一个顶点的连续序列
- 简单路径:要求路径中不包含重复顶点
- 回路:第一个顶点和最后一个顶点相同的路径称为回路
- 无向图:图中所有的边都是没有方向的
- 有向图:图中的边是有方向的
- 无权图:边没有权重,所有的边权重都一样
- 带权图:边有一定的权重,比如统计路径的距离等
无权图
带权图
邻接矩阵
- 1、邻接矩阵让每个节点和一个整数相关联,该整数作为数组的下标值,
- 2、我们用一个二维数组来表示顶点之间的连接
- 3、二维数组[0][2] -> A ->C, 1代表有连线,0代表无连线。自己到自己通常用0表示A->A
缺点:稀疏图,若顶点多,边少,则矩阵中存在大量的0,浪费计算机储存空间
邻接表 1、邻接表由图中每个顶点以及和定点相邻的顶点组成** 2、这个列表有很多种结构来存储:数组/链表/字典**
缺点:
- 1、邻接表计算“出度”是比较简单的(出度:指向别人的数量,入度:指向自己的数量)
- 2、邻接表如果需要计算有向图的“入度”,那么是一件非常麻烦的事情
- 3、它必须构造一个“逆邻接表”,才能有效计算“入度”,但是开发中“入度”相对用的较少
图的封装
//封装图结构
function Graph(){
//属性:顶点(数组)/边(字典)
this.vertexes = [] //顶点
this.edges = new Dictionay() //
//方法
//添加方法
// 1、添加顶点的方法
Graph.prototype.addVertex = function(v){
this.vertexes.push(v)
this.edges.set(v,[])
}
// 2、添加边的方法
Graph.prototype.addEdge = function(v1,v2){
this.edges.get(v1).push(v2)
this.edges.get(v2).push(v1)
}
//实现toString方法
Graph.prototype.toString = function(){
// 1、定义字符串,保存最终结果
let resultString = ''
//遍历所有的顶点,以及顶点对应的边
for(let i=0 ;i<this.vertexes.length; i++){
resultString += this.vertexes[i] + '->'
let vEdges = this.edges.get(this.vertexes[i])
for(let j=0; j<vEdges.length; j++){
resultString += vEdges[j] + ' '
}
resultString += '\n'
}
return resultString
}
//初始化状态颜色
Graph.prototype.initializeColor = function(){
let colors = []
for(let i=0; i<this.vertexes.length; i++){
colors[this.vertexes[i]] = 'white'
}
return colors
}
//实现广度优先搜索(BFS)
Graph.prototype.bfs = function(initV,handler){
//1、初始化颜色
let colors = this.initializeColor()
// 2、创建队列 引入之前封装的队列
let queue = new Queue()
// 3、将顶点加入到队列中
queue.enqueue(initV)
//4、循环从队列中取出元素
while(!queue.isEmpty()){
//4.1从队列取出衣蛾顶点
let v = queue.dequeuq()
//4.2获取和顶点项链的另外顶点
let vList = this.edges.get(v)
//4.3将V的颜色设置成灰色
colors[v] = 'gray'
//4.4遍历所有的顶点,并且加入到队列中
for(let i=0; i<vList.length; i++){
let e = vList[i]
if(colors[e] == 'white'){
colors[e] = 'gray'
queue.enqueue(e)
}
}
//4.5访问顶点
handler(v)
//4.6将顶点设置为黑色
colors[v] = 'black'
}
}
//实现深度优先搜索(DFS)
Graph.prototype.dfs = function(initV,handler){
//1、初始化颜色
let colors = this.initializeColor()
//2、从某个顶点进行依次递归访问
this.dfsVisit(initV,colors,handler)
}
Graph.prototype.dfsVisit = function(v, colors, handler){
//1、将颜色设置为灰色
colors[v] = 'gary'
//2处理v顶点
handle(v)
//3访问顶点项链的另外顶点
let vList = this.edges.get(v)
for(let i=0; i<vList.length; i++){
let e = vList[i]
if(colors[e] == 'white'){
this.dfsVisit(e,colors,handler)
}
}
//4.将顶点设置为黑色
colors[v] = 'black'
}
}
图的遍历思想(都需要指定第一个被访问的顶点)
- 1、广度优先算法(Breadth-First Search,简称BFS)
- 2、深度优先算法(Depth-First Search,简称DFS)