常用方法:
- addVertex(vertex)添加顶点的方法
- addEdge(vertexA, vertexB)添加边的方法
- toString()实现toString方法
- BFS & DFS
// 创建字典的构造函数
function Dictionary() {
// 字典属性
this.items = {}
// 字典操作方法
// 1 添加键值对
Dictionary.prototype.set = function (key, value) {
this.items[key] = value;
}
// 2 判断字典中是否有某个key
Dictionary.prototype.has = function (key) {
return this.items[key] != null
}
// 3 从字典中移除元素remove
Dictionary.prototype.remove = function (key) {
delete this.items[key]
return true
}
// 4 根据key去获取value
Dictionary.prototype.get = function (key) {
return this.has(key) ? this.items[key] : undefined
}
// 5 获取多有的keys
Dictionary.prototype.keys = function () {
return Object.keys(this.items)
}
// 6 获取所有的value
Dictionary.prototype.values = function () {
return Object.values(this.items)
}
// 7 size方法
Dictionary.prototype.size = function () {
// return Object.keys(this.items).length
return this.keys().length
}
// 8 clear方法
Dictionary.prototype.clear = function () {
this.items = {}
}
}
// 创建队列结构
function Queue () {
// 封装属性
this.items = [];
// 1 实现插入
Queue.prototype.enqueue = function (element){
this.items.push(element)
}
// 2 从队列中删除前端元素
Queue.prototype.dequeue = function (){
return this.items.shift()
}
// 3 查看前端元素
Queue.prototype.front = function (){
return this.items[0]
}
// 4 查看队列是否为空
Queue.prototype.isEmpty = function (){
return this.items.length === 0
}
// 5 查看队列个数
Queue.prototype.size = function (){
return this.items.length
}
// 6 toString方法
Queue.prototype.toString = function () {
let resultString = '';
for (let index = 0; index < this.items.length; index++) {
resultString += this.items[i] + ' ';
}
return resultString
}
}
//-----------------分割线--------------------------------
// 封装图结构
function Graph() {
// 属性:顶点(数组)/ 边(字典)
this.vertexes = []; //顶点
this.edges = new Dictionary(); //边
// 方法
// 添加方法
// 1 添加顶点的方法
Graph.prototype.addVertex = function (vertex) {
this.vertexes.push(vertex);
this.edges.set(vertex, []);
}
// 2 添加边的方法
Graph.prototype.addEdge = function (vertexA, vertexB) {
this.edges.get(vertexA).push(vertexB);
this.edges.get(vertexB).push(vertexA);
}
// 3 实现toString方法
Graph.prototype.toString = function () {
// 定义字符串,保存最终结果
let resultString = "";
// 遍历所有的顶点,以及顶点对应的边
for (let index = 0; index < this.vertexes.length; index++) {
resultString += this.vertexes[index] + "->";
let vEdges = this.edges.get(this.vertexes[index]);
for (let edgeIndex = 0; edgeIndex < vEdges.length; edgeIndex++) {
resultString += vEdges[edgeIndex] + " "
}
resultString += "\n"
}
return resultString
}
// 4 实现图搜索(BFS & DFS)
// 4.1 初始化顶点状态颜色
Graph.prototype.initializeColor = function () {
let colors = [];
for (let index = 0; index < this.vertexes.length; index++) {
// 白色white 未遍历处理, 灰色gray 已遍历未处理, 黑色black 已被遍历 已处理
colors[this.vertexes[index]] = "white" ;
}
return colors
}
// 4.2 广度优先搜索(BFS) 队列处理
// firstV表示传入的首个顶点, handle表传入的处理函数
Graph.prototype.bfs = function (firstV, handler) {
// 1 初始化颜色
let colors = this.initializeColor()
// 2 创建队列
let queue = new Queue();
// 3 将顶点加入到队列中,更改颜色
queue.enqueue(firstV);
colors[firstV] = "gray";
// 4 循环从队列中取出元素
while (! queue.isEmpty()) {
// 4.1 从队列中取出头元素,对其进行handle处理,并更改颜色
let v = queue.dequeue();
// 访问处理顶点
handler(v);
// 白色white 未遍历处理, 灰色gray 已遍历未处理, 黑色black 已被遍历 已处理
colors[v] = "black";
// 4.2 获取与顶点相连的其它顶点
let vList = this.edges.get(v);
// 4.3 将获取到的其它顶点加入到队列中
for (let index = 0; index < vList.length; index++) {
let otherV = vList[index];
// 判断顶点是否已经遍历过(是否未白色)
if (colors[otherV] == "white") {
colors[otherV] = "gray"; // 更改颜色
queue.enqueue(otherV);
}
}
// 将节点变为黑色
colors[firstV] = "black";
}
}
// 4.3 深度优先搜索(DFS) 栈或者递归
Graph.prototype.dfs = function (firstV, handler) {
// 1 初始化颜色
let colors = this.initializeColor();
// 2 从某个顶点开始依次递归访问
this.dfsVisit(firstV, colors, handler);
}
Graph.prototype.dfsVisit = function (v, colors, handler) {
// 1 更改颜色
colors[v] = "gray";
// 2 处理顶点
handler(v);
// 3 递归遍历其它节点
// 3.1 获取该顶点所连接项
let vList = this.edges.get(v);
for (let index = 0; index < vList.length; index++) {
let vListItem = vList[index];
if (colors[vListItem] == "white") {
this.dfsVisit(vListItem, colors, handler)
}
}
// 将该节点变为黑色
colors[v] = "black";
}
}
// 测试代码
// 1 创建图结构
let graph = new Graph();
// 2 添加顶点
let myVertexes = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
for (let index = 0; index < myVertexes.length; index++) {
graph.addVertex(myVertexes[index]);
}
// 3 添加边
let myEdges = [
['A', 'B'],
['A', 'C'],
['A', 'D'],
['C', 'D'],
['C', 'G'],
['D', 'G'],
['D', 'H'],
['B', 'E'],
['B', 'F'],
['E', 'I'],
]
for (let index = 0; index < myEdges.length; index++) {
let value = myEdges[index];
graph.addEdge(value[0], value[1]);
}
console.log(graph.toString());
// 4 测试BFS搜索
console.log("BFS搜索开始:");
let result = '';
graph.bfs(graph.vertexes[0], function (vertex) {
result += vertex + ' ';
})
console.log(result);
// 5 测试DFS搜索
console.log("DFS搜索开始:");
result = '';
graph.dfs(graph.vertexes[0], function (vertex) {
result += vertex + ' ';
})
console.log(result);