深度优先算法与最小生成树
2018-09-22 本文已影响0人
勃列日涅夫
- 深度优先搜索(DFS),可以被形象的描述为“打破沙锅问到底”,具体一点就是访问一个顶点之后,我继而访问它的下一个邻接的顶点,如此往复,直到当前顶点一被访问或者它不存在邻接的顶点。
以下为深度优先算法的规则 - 规则1、:访问一个邻接的未访问的节点,标记它,并把它放入栈中
- 规则2、当不能执行规则1是,从栈弹出一个顶点
- 规则3、如果不能完成规则1 规则2则完成搜索
对于最小生成树,和深度优先算法相似,具体区别是多一个记录,如下mst方法
/**
*
*/
package com.xzg.heap;
/**
* @author hasee
* @TIME 2017年5月2日
* 1、图的表示,使用临接表或邻接矩阵
* 2、深度优先搜索算法,核心:栈。规则1、:访问一个邻接的未访问的节点,标记它,并把它放入栈中
* 规则2、当不能执行规则1是,从栈弹出一个顶点
* 规则3、如果不能完成规则1 规则2则完成搜索
*/
public class DeepSearch {
//测试
public static void main(String[] args){
Graph theGraph = new Graph();
theGraph.addVertex('A');
theGraph.addVertex('B');
theGraph.addVertex('C');
theGraph.addVertex('D');
theGraph.addVertex('E');
theGraph.addEdge(0, 1);//ab
theGraph.addEdge(1, 2);//BC
theGraph.addEdge(0, 3);//AD
theGraph.addEdge(3, 4);//DE
theGraph.dfs();
}
}
/**
* @author hasee
* @TIME 2017年5月2日
* 简单实现栈
*/
class StackX{
//初始大小
private final int SIZE = 20;
private int[] st;
private int top;
public StackX(){
st = new int[SIZE];
top =-1;
}
public void push(int j){
st[++top] = j;
}
public int pop(){
return st[top--];
}
public int peek(){
return st[top];
}
public boolean isEmpty(){
return top == -1;
}
}
/**
* @author hasee
* @TIME 2017年5月2日
* 作为储存搜索的节点,包括数值和是否访问过的标志位
*/
class Vertx{
public char lable;
public boolean wasVisited;
public Vertx(char lab){
this.lable = lab;
this.wasVisited = false;
}
}
class Graph{
private final int MAX_VRERTS = 20;
private Vertx vertxList[];//包含所有的节点信息
private int adjMat[][];//邻接矩阵
private int nVert;//当前vertxList的指向下标
private StackX theaStack;
//初始化
public Graph(){
vertxList = new Vertx[MAX_VRERTS];
adjMat = new int[MAX_VRERTS][MAX_VRERTS];
nVert = 0;
for(int j=0;j<MAX_VRERTS;j++)
for(int k = 0;k<MAX_VRERTS;k++)
adjMat[j][k] = 0;
theaStack = new StackX();
}
/**
* @param lab
*/
public void addVertex(char lab){
vertxList[nVert++] = new Vertx(lab);
}
/**
* @param start
* @param end
* 邻接矩阵,添加执行的
*/
public void addEdge(int start,int end){
adjMat[start][end] = 1;
adjMat[end][start] = 1;
}
/**
* @param v
* 展示节点数值
*/
public void display(int v){
System.out.println(vertxList[v].lable);
}
/**
* 深度优先搜索
* 1、使用peek方法获取栈顶2、试图找到这个栈顶还未访问的邻接点
* 3、如果没有找到出栈 4、如果找到则把这个节点push到栈中
*/
public void dfs(){
vertxList[0].wasVisited = true;//顶点标记为已读
display(0);
//初始一个栈顶为0
theaStack.push(0);
//只要不为空,就继续搜索
while(!theaStack.isEmpty()){
//theaStack.peek获取当前的顶点
int v = getAdjUnivisitedVertx(theaStack.peek());
if(v == -1){
theaStack.pop();
}
else{
vertxList[v].wasVisited = true;
display(v);
theaStack.push(v);
}
}//重置标志位
for(int j=0;j<nVert;j++){
vertxList[j].wasVisited = false;
}
}
/**
* 深度优先算法实现最小生成树
*/
public void mst(){
vertxList[0].wasVisited = true;
theaStack.push(0);
while(! theaStack.isEmpty()){
int curentVertx = theaStack.peek();
int v = getAdjUnivisitedVertx(curentVertx);
//表示已经没有邻接点
if(v == -1){
theaStack.pop();
}else{
vertxList[v].wasVisited = true;
theaStack.push(v);
//这里是最小生成树保存
display(curentVertx);//起点
display(v);//终点
}
for(int i=0;i<nVert;i++)
vertxList[i].wasVisited = true;
}
}
/**
* @param v
* @return
* 深度优先算法关键是找到邻接且没有被访问过的点。
*/
public int getAdjUnivisitedVertx(int v){
for(int i=0;i<nVert;i++){
if(adjMat[v][i] == 1 &&vertxList[i].wasVisited == false)
return i;
}
return -1;
}
}