图的搜索(广度优先)
程序员文章站
2022-06-12 19:11:16
...
一:广度优先规则
1.访问下一个邻接的未访问过的顶点,这个顶点必须是当前顶点的邻接点,标记他,并把它插入到队列中
2.如果无法执行规则1,那么就从队列头取出一个顶点,并使其作为当前顶点
3.当队列为空不能执行规则2时,就是搜索完成时.
二:代码实现
1.创建队列
public class Quene {
//队列底层也是数组
long[] arr;
//队列长度
int length;
//队头
int front;
//队尾
int end;
//构造方法
public Quene(){
arr = new long[10];
length=0;
front=0;
end=-1;
}
public Quene(int size){
arr = new long[size];
length=0;
front=0;
end=-1;
}
//1.添加数据,从队列尾插入
public void insert(long value){
arr[++end] = value;
length++;
}
//2.删除数据,从队头开始
public long romove(){
length--; //长度减减
return arr[front++]; //把第一个数据移除,队头就会++
}
//3.查看数据,从队头查看
public long peek(){
return arr[front];
}
//4.判断是否为空
public boolean isEmpty(){
return length==0;
}
//5.判断是否满了
public boolean isFull(){
return length == arr.length;
}
}
2.创建顶点
//顶点类
public class Vertex {
//顶点名称
public char label;
//添加是否被访问属性
public boolean wasVisited;
public Vertex( char label){
this.label = label;
}
}
3.创建图
//图
public class Graph {
//顶点数组
private Vertex[] vertexList;
//邻接矩阵,二维数组
private int[][] arr;
//顶点最大数量
private int maxSize = 20;
//已添加顶点数量
private int vt;
//引入已创建的建栈,用于存储搜索的数据
private Quene quene;
public Graph(){
//初始化顶点数组
vertexList = new Vertex[maxSize];
//初始化邻接矩阵
arr = new int[maxSize][maxSize];
//初始化值
for (int i= 0;i<maxSize;i++){
for (int j= 0;j<maxSize;j++){
//代表所有的边都不相连
arr[i][j] = 0;
}
}
vt = 0;
//初始化栈
quene = new Quene();
}
//添加顶点
public void addVertex(char label){
//往顶点数组内添加顶点
vertexList[vt++] = new Vertex(label);
}
//添加边
public void addEdge(int start , int end){
//从 start 到 end 连通
arr[start][end] = 1;
//从 end 到 start 自然也连通
arr[end][start] = 1;
}
//查找节点
//参数 v : 代表从哪个节点开始找(前提是这个节点未被访问过)
public int getVertex(int v){
//在邻接矩阵里面找未被访问过的节点
for (int i = 0; i < vt; i++){
//判断节点之间是否相邻 同时 是否未被访问
if (arr[v][i] == 1 && vertexList[i].wasVisited == false){
//当该v和i节点相邻且i节点未被访问过,则返回
return i;
}
}
return -1;
}
//广度优先搜索
public void bfs(){
//首先访问 0 号顶点
vertexList[0].wasVisited = true;
//显示被访问的顶点
displayVertex(0);
//把0顶点插入队列
quene.insert(0);
//循环访问顶点,当队列不为空的时候,取出头节点再插入其邻接点
while (!quene.isEmpty()){
//获得队列头节点的一个未访问的邻接点
int v = getVertex((int)quene.peek());
//找不到的情况
if (v == -1){
//取出队列头节点
quene.romove();
}else{
//找得到则标记再顶点压栈
vertexList[v].wasVisited = true;
//显示
displayVertex(v);
quene.insert(v);
}
}
//搜索完成后,复原
for (int i = 0; i < vt ; i++){
vertexList[i].wasVisited = false;
}
}
//显示
public void displayVertex(int v){
System.out.println(vertexList[v].label);
}
}
4.测试
public class Test {
public static void main(String[] args) {
//添加顶点
Graph graph = new Graph();
graph.addVertex('A');
graph.addVertex('B');
graph.addVertex('C');
graph.addVertex('D');
graph.addVertex('E');
graph.addVertex('F');
//添加边
graph.addEdge(0,1);
graph.addEdge(1,2);
graph.addEdge(0,3);
graph.addEdge(3,4);
graph.addEdge(0,5);
//广度优先搜索
graph.bfs(); //A B D F C E
}
}