深度优先算法
深度优先百度百科
深度优先遍历图的方法是,从图中某顶点v出发:
(1)访问顶点v;
(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。
有点不太好理解
就如图所示 整个节点构成的图 是一个二维数组,当进行深度优先的时候先以黑色箭头为指向的下标节点开始搜索,先搜索 arr[0][index] 开始找到存在通路的第一个节点且该节点没有被访问过,找到后就将黑色箭头移到对应的index 即 black_index = index, 然后继续搜索,找到第一个通路的节点,当节点被访问过就继续查找arr[black_index][index]的下一个节点是否是通路,如果找到了继续移动黑色箭头。
简单的说 直接搜索对应的black_index 对应的一维数组中依次查找能够联通的节点,找到了就从红色箭头代表的index 赋值给 black_index 然后再再这个black_index中查找,并标记已经查找过的节点,如果第一次还没搜索完成,那么就将black_index 加 1 后再查找。
namespace DataStructure {
export class MapGrap {
private edges: number[][]; // 边对应的数据
private vertexs: string[]; // 顶点数据
private numberOfEdges: number; // 总共的边数
private isVisited: boolean[]; // 顶点是否被访问过
constructor(vertex: number) {
this.vertexs = new Array<string>();
this.isVisited = new Array<boolean>(vertex);
this.edges = new Array<Array<number>>(vertex);
for (let i = 0; i < this.edges.length; i++) {
this.edges[i] = new Array<number>(vertex);
for (let j = 0; j < this.edges[i].length; j++) {
this.edges[i][j] = 0; // 初始化权值都是 0
}
}
this.numberOfEdges = 0;
}
/**
* 深度搜索
*/
public dfs() :void{
for (let index = 0; index < this.edges.length; index++) { // for循环查找所有节点
if(! this.isVisited[index]){
this.dfsSearch(this.isVisited, index);
}
}
}
public dfsSearch(_isVisited: boolean[], row: number): void {
console.log(this.getVertexName(row) +" -- >");
let first = this.getFirstNeightbour(row);
_isVisited[row] = true;
while(first != -1){
if(! _isVisited[first]){
this.dfsSearch(_isVisited, first);
}
first = this.getNextNeightbour(row, first);
}
}
/** 获取下一个顶点,通过startCol来确定起始的位置,减少多余的操作 */
private getNextNeightbour(row: number, startCol: number) : number{
for (let index = startCol+1; index < this.edges[row].length; index++) {
if (this.edges[row][index] > 0) {
return index;
}
}
return -1;
}
/** 查找第一个邻近的顶点 */
private getFirstNeightbour(row: number): number {
for (let index = 0; index < this.edges[row].length; index++) {
if (this.edges[row][index] > 0) {
return index;
}
}
return -1;
}
public getEdgesWeight(v1: number, v2: number): number {
return this.edges[v1][v2];
}
public printMap(): void {
console.log("地图打印: -------------------------------");
console.table(this.edges);
for (const rows of this.edges) {
}
}
/**
* 添加顶点
* @param vertex 顶点字符串
*/
public addVertex(vertex: string): void {
this.vertexs.push(vertex);
}
/**
* 插入一条边
* @param v1 顶点一
* @param v2 顶点二
* @param weight 权重 或者 你需要的边长路径之类的
*/
public insertEdge(v1: number, v2: number, weight: number): void {
if (!this.edges[v1]) {
this.edges[v1] = new Array<number>(this.getVertexLen());
}
if (!this.edges[v2]) {
this.edges[v2] = new Array<number>(this.getVertexLen());
}
this.edges[v1][v2] = weight;
this.edges[v2][v1] = weight;
this.numberOfEdges++;
}
public getVertexLen(): number {
return this.vertexs.length;
}
public getVertexName(index: number): string {
return this.vertexs[index];
}
}
}