出度、入度
- 出度:节点指向多少个节点
- 入度:有多少个节点指向该节点
- 有向图:每个节点是有方向的
- 无向图:每个节点无方向,可以相互指向,互为出入度
邻接表
邻接矩阵
- 通过矩阵表示,A-A的权重为0,A-C的权重为7,…
宽度遍历
- 宽度遍历的结果为:A、C、B、E、D,其中CBE的顺序无所谓,相比于二叉树的宽度遍历,因为图有指向自身或已遍历节点的方向,所以需要处理这样的环结构的问题
function BFS(node) {
let arr = [];
let unique = new Set();
arr.push(node);
unique.add(node);
for (let i = 0; i < arr.length; i++) {
let tempNode = arr[i];
console.log(tempNode.value);
let nexts = tempNode.nexts || [];
for (let j = 0; j < nexts; j++) {
let nextNode = nexts[j];
if (unique.has(nextNode)) {
return;
}
arr.push(nextNode);
unique.add(nextNode);
}
}
}
深度遍历
- 深度优先遍历:如果从B进入的话,ABCDE
- 深度优先遍历准备一个栈结构,是当一个节点进去的时候处理,同样需要处理节点的指向自身或已遍历节点形成的环的问题(Set)
- 如果当前节点指向的最近的节点未遍历,就将当前节点和指向的节点一起加入栈中,输出指向的节点,然后终止掉,从指向的节点开始遍历,即弹出栈顶元素
- 重复上一步,当指向的节点不再有指向的节点时,因为每次存入的都是一对节点和节点指向的节点,所以会继续弹出栈顶元素,即指向之前弹出节点的那个节点,恢复路径,继续走上一步,因为会有去重判断,所以恢复的路径节点,不会再遍历已经遍历过的指向节点
function DFS(node) {
let stack = [];
let unique = new Set();
stack.push(node);
unique.add(node);
console.log(node.value);
while (stack.length) {
let tempNpde = stack.pop();
let nexts = tempNpde.nexts;
for (let i = 0; i < nexts.length; i++) {
let nextNode = nexts[i];
if (!unique.has(nextNode)) {
stack.push(tempNpde);
stack.push(nextNode);
unique.add(nextNode);
console.log(nextNode.value);
break;
}
}
}
}