实现队列
function Queue() {
this.items = []
Queue.prototype.enqueue = function (ele) {
this.items.push(ele);
}
Queue.prototype.dequeue = function () {
return this.items.shift();
}
Queue.prototype.front = function () {
return this.items[0];
}
Queue.prototype.isEmpty = function () {
return this.items.length == 0;
}
Queue.prototype.size = function () {
return this.items.length;
}
Queue.prototype.toString = function () {
var resultStr = '';
for (var i = 0; i < this.items.length; i++) {
resultStr += this.items[i];
}
return resultStr;
}
}
module.exports = Queue;
实现字典
function Dictionary() {
this.items = {};
this.set = function (key, value) {
return this.items[key] = value;
}
this.has = function (key) {
return this.items.hasOwnProperty(key);
}
this.remove = function (keu) {
if (this.has(key)) {
delete this.items[key];
return true;
}
return false;
}
this.get = function (key) {
return this.has(key) ? this.items[key] : undefined;
}
// 获取所有keys
this.keys = function () {
return Object.keys(this.items);
}
//获取所有values
this.values = function () {
return Object.values(this.items);
}
this.size = function () {
return Object.keys(this.items).length;
}
this.clear = function () {
this.items = {};
}
this.getItems = function () {
return this.items;
}
}
module.exports = Dictionary;
图
图的遍历
- 广度优先搜索(Breadth-First Search,BFS)
- 深度优先搜索(Depth-First Search,DFS)
- 两个遍历算法,都需要明确指定第一个被访问的顶点
记录状态
白色:表示该顶点还没有被访问
灰色:表示该顶点被访问过,但并未探索过
黑色:表示该顶点被访问过且完全探索过
const Dict = require("./dict")
var print = console.log;
function Graph() {
// 顶点
this.vertices = [];
// 边
this.edges = new Dict();
Graph.prototype.addVertex = function (v) {
this.vertices.push(v);
this.edges.set(v, []);
}
Graph.prototype.addEdge = function (v1, v2) {
this.edges.get(v1).push(v2);
this.edges.get(v2).push(v1);
}
Graph.prototype.toString = function () {
var resultStr = "";
for (var i = 0; i < this.vertices.length; i++) {
resultStr += this.vertices[i] + "->"
var vEdges = this.edges.get(this.vertices[i]);
for (var j = 0; j < vEdges.length; j++) {
resultStr += vEdges[j] + " ";
}
resultStr += "\n";
}
return resultStr
}
}
var g = new Graph();
var myVertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
for (var i = 0; i < myVertices.length; i++) {
g.addVertex(myVertices[i]);
}
g.addEdge('A', 'B');
g.addEdge('A', 'C');
g.addEdge('A', 'D');
g.addEdge('C', 'D');
g.addEdge('C', 'G');
g.addEdge('D', 'G');
g.addEdge('D', 'H');
g.addEdge('B', 'E');
g.addEdge('B', 'F');
g.addEdge('E', 'I');
print(g.edges);
广度 优先搜索
- 广度优先算法从指定的第一个顶点开始遍历图,先访问其所有的相邻接点,就像一次访问图的一层
- 先宽后深的访问顶点
// 广度优先搜索(BFS)
Graph.prototype.bfs = function (initV, handler) {
// 1.初始化颜色
var color = this.initializeColor();
// 2.创建队列
var queue = new Queue();
// 3.将顶点加入队列中
queue.enqueue(initV);
// 4.循环从队列中取出元素
while (!queue.isEmpty()) {
// 4.1.从队列取出一个顶点
var v = queue.dequeue();
// 4.2.获取顶点和相连的另外顶点
var vList = this.edges.get(v);
// 4.3.将v的颜色设置灰色
color[v] = 'gray';
// 4.4.遍历所有的顶点,并且加入到队列中
for (var i = 0; i < vList.length; i++) {
var e = vList[i];
if (color[e] == 'white') {
color[e] = 'gray';
queue.enqueue(e);
}
}
// 4.5.v已经被探测,并且返回
handler(v);
// 4.6.将顶点设置为黑色
color[v] = 'black';
}
//
}
}
var result = '';
g.bfs(g.vertices[0], function (v) {
result += v + ' ';
})
print(result) // A B C D E F G H I
深度 优先搜索
- 深度优先搜索算法会从第一个指定的顶点开始遍历图,沿着路径知道这条路径最后被访问了
- 接着原路回退并探索一条路径
// 深度优先搜索(DFS)
Graph.prototype.dfs = function (initV, handler) {
// 1.初始化颜色
var color = this.initializeColor();
// 2.从某个顶点开始依次递归访问
this.dfsVisit(initV, color, handler);
}
Graph.prototype.dfsVisit = function (v, color, handler) {
// 1.将颜色设置为灰色
color[v] = 'gray';
// 2.处理v顶点
handler(v);
// 3.访问v相连的顶点
var vList = this.edges.get(v);
for (var i = 0; i < vList.length; i++) {
var e = vList[i];
if (color[e] == 'white') {
this.dfsVisit(e, color, handler);
}
}
// 4.将v设置为黑色
color[v] = 'black';
}
var result = '';
g.dfs(g.vertices[0], function (v) {
result += v + ' ';
})
print(result); // A B E I F C D G H
总代码
const Dict = require('./dict');
const Queue = require('./queue');
var print = console.log;
function Graph() {
// 顶点
this.vertices = [];
// 边
this.edges = new Dict();
Graph.prototype.addVertex = function (v) {
this.vertices.push(v);
this.edges.set(v, []);
}
Graph.prototype.addEdge = function (v1, v2) {
this.edges.get(v1).push(v2);
this.edges.get(v2).push(v1);
}
Graph.prototype.toString = function () {
var resultStr = '';
for (var i = 0; i < this.vertices.length; i++) {
resultStr += this.vertices[i] + '->'
var vEdges = this.edges.get(this.vertices[i]);
for (var j = 0; j < vEdges.length; j++) {
resultStr += vEdges[j] + ' ';
}
resultStr += '\n';
}
return resultStr
}
// 初始化状态颜色
Graph.prototype.initializeColor = function () {
var colors = [];
for (var i = 0; i < this.vertices.length; i++) {
colors[this.vertices[i]] = 'white';
}
return colors
}
// 广度优先搜索(BFS)
Graph.prototype.bfs = function (initV, handler) {
// 1.初始化颜色
var color = this.initializeColor();
// 2.创建队列
var queue = new Queue();
// 3.将顶点加入队列中
queue.enqueue(initV);
// 4.循环从队列中取出元素
while (!queue.isEmpty()) {
// 4.1.从队列取出一个顶点
var v = queue.dequeue();
// 4.2.获取顶点和相连的另外顶点
var vList = this.edges.get(v);
// 4.3.将v的颜色设置灰色
color[v] = 'gray';
// 4.4.遍历所有的顶点,并且加入到队列中
for (var i = 0; i < vList.length; i++) {
var e = vList[i];
if (color[e] == 'white') {
color[e] = 'gray';
queue.enqueue(e);
}
}
// 4.5.v已经被探测,并且返回
handler(v);
// 4.6.将顶点设置为黑色
color[v] = 'black';
}
}
// 深度优先搜索(DFS)
Graph.prototype.dfs = function (initV, handler) {
// 1.初始化颜色
var color = this.initializeColor();
// 2.从某个顶点开始依次递归访问
this.dfsVisit(initV, color, handler);
}
Graph.prototype.dfsVisit = function (v, color, handler) {
// 1.将颜色设置为灰色
color[v] = 'gray';
// 2.处理v顶点
handler(v);
// 3.访问v相连的顶点
var vList = this.edges.get(v);
for (var i = 0; i < vList.length; i++) {
var e = vList[i];
if (color[e] == 'white') {
this.dfsVisit(e, color, handler);
}
}
// 4.将v设置为黑色
color[v] = 'black';
}
}
var g = new Graph();
var myVertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
for (var i = 0; i < myVertices.length; i++) {
g.addVertex(myVertices[i]);
}
g.addEdge('A', 'B');
g.addEdge('A', 'C');
g.addEdge('A', 'D');
g.addEdge('C', 'D');
g.addEdge('C', 'G');
g.addEdge('D', 'G');
g.addEdge('D', 'H');
g.addEdge('B', 'E');
g.addEdge('B', 'F');
g.addEdge('E', 'I');
print(g.edges.items);
var result = '';
g.bfs(g.vertices[0], function (v) {
result += v + ' ';
})
print(result);
var result = '';
g.dfs(g.vertices[0], function (v) {
result += v + ' ';
})
print(result);
输出: