您的位置:首页 > 编程语言 > Java开发

深度优先遍历 广度优先遍历JAVA

2017-11-25 16:50 351 查看
package graph;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
* @Author GJL
* @Desription
* @Date 2017/11/25
* @Modified By:
**/
public class BFS {

public static void main(String[] args) {
Graph graph = new Graph(6);

graph.addNode(new GraphNode("A"));
graph.addNode(new GraphNode("B"));
graph.addNode(new GraphNode("C"));
graph.addNode(new GraphNode("D"));
graph.addNode(new GraphNode("E"));
graph.addNode(new GraphNode("F"));

graph.addEdge(0,1);
graph.addEdge(0,2);
graph.addEdge(0,3);
graph.addEdge(1,4);
graph.addEdge(2,4);
graph.addEdge(3,4);
graph.addEdge(4,5);

//graph.bfs(0);
graph.printMatrx();
System.out.println();
graph.dfs(0);
}
}

class Graph{
//保存节点的数组
GraphNode [] graphNodes;
//初始化时候 数组的大小
int size;
//加入节点时候 已经存在的节点数
int curSize;
//保存节点之间的联通关系
int[][] relation;

public Graph(int size) {
this.graphNodes = new GraphNode[size];
this.size = size;
this.curSize = 0;
this.relation = new int[size][size];
}
public void addNode(GraphNode graphNode){
if(curSize<=size){
graphNodes[curSize++] = graphNode;
}else{
System.out.println("节点数组已满");
}
}
public void addEdge(int start,int end){
if(start<size && end<size){

relation[start][end] = 1;
relation[end][start] = 1;

}else{
System.out.println("请输入正确的start end");
}

}
/**
* @param nodeIndex 节点数组下标
*/
public void bfs(int nodeIndex){
//利用队列 来存储那些与 已经遍历节点的相连节点索引
LinkedList list = new LinkedList();
//节点设置访问值为 true  节点索引入队列
graphNodes[nodeIndex].setVisted(true);
list.offer(nodeIndex);
while(!list.isEmpty()){
//获取索引
int index = (int)list.poll();
//获取节点 并打印 name值
System.out.println( graphNodes[index].getName());

for(int i = 0;i<curSize;i++){
if(!graphNodes[i].getVisted() && relation[index][i] == 1){
//如果该节点与index节点联通 获取 该节点 并把该节点置位访问过
GraphNode node = graphNodes[i];
node.setVisted(true);
//入队列
list.offer(i);

}
}

}

}
//深度优先搜索 利用栈 可以尝试使用LinkedList 或者自己实现栈结构 入栈 addFirst() 出栈 removeFirst() 获取 栈顶元素 getFirst()
public void dfs(int nodeIndex){
LinkedList<Integer> list = new LinkedList();
//设置改图的第一个索引节点为 遍历 过后 的状态
graphNodes[nodeIndex].setVisted(true);
//打印 其name 值
System.out.println(graphNodes[nodeIndex].getName());
//将该节点索引入栈
list.addFirst(nodeIndex);
//当栈 不为空时候 一直循环
while(!list.isEmpty()){
//只是取出栈顶的index值 (并没有删除 节点)
int index = list.getFirst();
//调用 一个 获取 当前节点 的联通节点的索引 函数 获取 其中 一个 可用索引(即 并未 遍历过)//从这 我们 可以看出 list 维护的列表的大小 一层只是 一个 这就是深度搜索 优于 广度遍历 的地方 占用内存 少一点
int j = getNextAdjNodeIndex(index);
//如果 获取 到 索引 那么 对应节点 置为 访问过 并且 打印 入栈,否则 出栈 (后续再 继续 循环 回溯)
if(j!= -1){
graphNodes[j].setVisted(true);
System.out.println(graphNodes[j].getName());
list.addFirst(j);
}else{
list.removeFirst();
}
}

}
//通过索引p来获取 邻接矩阵中与该 节点联通 的 节点索引
private int getNextAdjNodeIndex(int p) {
for(int i=0; i<curSize;i++){
if(!graphNodes[i].getVisted() && relation[p][i] == 1){
return i;
}
}
return -1;
}

public void printMatrx(){
for(int[] arr: relation){
System.out.println();
for(int i:arr){
System.out.print(i);
}
}

}

}

class GraphNode{
private String name;
private  boolean visted;

public GraphNode(String name) {
this.name = name;
this.visted = false;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public boolean getVisted() {
return visted;
}

public void setVisted(boolean visted) {
this.visted = visted;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: