Table of contents
Chapter 9 "Graph" of Data Structure
9.1 Introduction to graphs
An edge can connect at most two nodes.
Graphs can also be constructed using linked lists.
9.2 Depth- and breadth-first traversal of graphs
Create a new graph in the tu.js file:
// 利用objct和Array构建一个图
var tu = {
0: [1, 2],
1: [2],
2: [0, 3],
3: [3]
}
module.exports = tu;
Do a depth-first traversal of the graph:
var tu = require("./tu");//1、引入构造图的JS文件
var visited = new Set();//4、新建一个空字典,用来存放已经访问过的节点
var dfs = (n) => {
//2、声明一个箭头函数,把要访问的节点传进去
console.log(n);//3、访问当前节点
visited.add(n);//5、把已经访问过的节点,放到字典中,方便以后不再访问
tu[n].forEach(c => {
//6、访问当前节点的相邻节点,但要排除已经访问过的节点
if (!visited.has(c)) {
//7、排除已经访问过的节点,之前访问过的节点就不再访问了
dfs(c);//8、递归调用它自己,重复之前的操作
}
});
}
dfs(2);//9、从2节点开始,2相当于根节点
Create a new graph in the tu.js file:
// 利用objct和Array构建一个图
var tu = {
0: [1, 2],
1: [2],
2: [0, 3],
3: [3]
}
module.exports = tu;
Breadth-first traversal of the graph:
var tu = require("./tu");//1、引入构造图的JS文件
var visited = new Set();//3、新建一个空字典,用来存放已经访问过的节点
var queue = [2];//2、把根节点入队
visited.add(2);//4、把根节点添加到字典中,表示已经访问过了
while (queue.length) {
//5、在队列在值的情况下进行当前元素的出队并访问操作
var n = queue.shift(n);//6、在队头出队
console.log(n);//7、访问当前元素
tu[n].forEach(c => {
//8、访问当前节点的相邻节点,但要排除已经访问过的节点
if (!visited.has(c)) {
//9、排除已经访问过的节点,之前访问过的节点就不再访问了
queue.push(c);//10、没有访问过的节点入队
visited.add(c);//11、把入队的节点添加到字典中,表示已经访问过了
}
});
}
9.3 LeetCode: 65. Significant Digits
Code:
//有效数字
var isNumber = function (s) {
var graph = {
0: {
'blank': 0, 'sign': 1, '.': 2, 'digit': 6 },
1: {
'digit': 6, '.': 2 },
2: {
'digit': 3 },
3: {
'digit': 3, 'e': 4 },
4: {
'digit': 5, 'sign': 7 },
5: {
'digit': 5 },
6: {
'digit': 6, '.': 3, 'e': 4 },
7: {
'digit': 5 }
};
let state = 0;
for (c of s.trim()) {
if (c >= '0' && c <= '9') {
c = 'digit';
} else if (c === ' ') {
c = 'blank';
} else if (c === '+'||c==='-') {
c = 'sign';
}
state = graph[state][c];
if(state===undefined){
return false;
}
}
if(state==3||state===5||state===6){
return true;
}
return false;
};
Code Interpretation:
Construct a graph:
reverse the corresponding characters to corresponding operations:
9.4 LeetCode: 417. Pacific-Atlantic Current Problem
Code:
// 太平洋
var pacificAtlantic = function (matrix) {
if (!matrix || !matrix[0]) {
return []; }
const m = matrix.lenth;
const n = matrix[0].lenth;
const flow1 = Array.from({
length: m }, () => new Array(n).fill(false));
const flow2 = Array.from({
length: m }, () => new Array(n).fill(false));
const dfs = (r, c, flow) => {
flow[r][c] = true;
[[r - 1, c], [r + 1, c], [r, c - 1], [r, c + 1]].forEach(([nr, nc]) => {
if (
// 保证在矩阵中
nr >= 0 && nr < m &&
nc >= 0 && nc < n &&
// 防止死循环
!flow[nr][nc] &&
// 保证逆流而上
matrix[nr][nc] >= matrix[r][c]
) {
dfs(nr, nc, flow);
}
});
};
// 沿着海岸线逆流而上
for (let r = 0; r < m; r += 1){
dfs(r, 0, flow1);
dfs(r, n-1, flow2);
}
for (let c = 0; c < n; c += 1){
dfs(0, c, flow1);
dfs(m-1, c, flow2);
}
// 收集能流到两个大洋里的坐标
const res = [];
for (let r = 0; r <m;r+=1){
for(let c = 0; c <n;c+=1){
if(flow1[r][c]&&flow2[r][c]){
res.push([r,c]);
}
}
}
return res;
};
Code interpretation:
exclude the case where the matrix is empty or the incoming one-dimensional array:
build two own matrices:
get the number of rows and columns of the matrix:
9.5 LeetCode: 133. Clone Graph
Method 1: Use depth-first traversal to do it.
Code:
var cloneGraph=function(node){
if(!node) return;
const visited = new Map();
visited.set(node,new Node(node.val));
const q=[node];
while(q.length){
const n=q.shift();
(n.neighbors||[]).forEach(ne => {
if(!visited.has(ne)){
q.push(ne);
visited.set(ne,new Node(ne.val));
}
visited.get(n).neighbors.push(visited.get(ne));
});
}
return visited.get(node);
};
Code interpretation:
Depth-first traversal graph:
Copy each node, but no relationship has been established:
Establish the mapping relationship between the original node and the copied node, but no edge has been established.
Establishing edges:
Method 2: Use breadth-first traversal to do it.
Code implementation:
breadth-first traversal graph:
9.6 Figure Summary