先简单记录基础逻辑。深度优先基于栈,广度优先基于队列。
使用的都是邻接矩阵而非邻接表。输出没有显示路径层次。
//深度优先DFS
class StackX {
private int[] st;
private final int size = 20;
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;
}
}
// 顶点
class Vertex {
char label;
boolean visited;
public Vertex(char label) {
this.label = label;
visited = false;
}
}
public class Graph {
private final int maxVer = 20;// 最大顶点数
private int[][] adjMat;// 邻接矩阵
private Vertex[] vertex;// 顶点数组
private int curVer;// 当前顶点数
private StackX stack;
public Graph() {
curVer = 0;
stack = new StackX();
vertex = new Vertex[maxVer];
adjMat = new int[maxVer][maxVer];
for (int i = 0; i < maxVer; i++)
for (int j = 0; j < maxVer; j++)
adjMat[i][j] = 0;
}
// 添加顶点
public void addVer(char label) {
vertex[curVer++] = new Vertex(label);
}
// 添加边
public void addAdj(int i, int j) {
if (i == j)// 自己与自己无边
return;
adjMat[i][j] = 1;
adjMat[j][i] = 1;
}
public void displayVer(int index) {
System.out.print(vertex[index].label);
}
public void dfs(int index) {
vertex[index].visited = true;
displayVer(index);
stack.push(index);
int k;
while (!stack.isEmpty()) {
k = findUnvisitedAdj(stack.peek());
if (k == -1)
stack.pop();
else {
stack.push(k);
vertex[k].visited = true;
displayVer(k);
}
}
// 搜索一次后重置访问状态,便于下次搜索
for (int i = 0; i < curVer; i++)
vertex[i].visited = false;
}
// 找到一个未访问过的相邻顶点
public int findUnvisitedAdj(int index) {
for (int i = 0; i < curVer; i++)
if (adjMat[index][i] == 1 && vertex[i].visited == false)
return i;
return -1;
}
public static void main(String[] args) {
Graph g = new Graph();
g.addVer('A');
g.addVer('B');
g.addVer('C');
g.addVer('D');
g.addVer('E');
g.addVer('F');
g.addAdj(0, 1);
g.addAdj(1, 2);
g.addAdj(2, 3);
g.addAdj(3, 5);
g.addAdj(0, 5);
g.addAdj(1, 4);
g.dfs(0);
}
}
//BFS
class Que {
static final int size = 20;
private int[] array;
private int front;
private int rear;
public Que() {
array = new int[size];
front = 0;
rear = -1;
}
public void add(int key) {
if (rear == size - 1)// 满了覆盖加入,满了是否禁止加好?
rear = -1;
array[++rear] = key;
}
public boolean isEmpty() {
return (front + size - 1 == rear || rear + 1 == front);
}
public int removeFirst() {//此处不需判断是否为空,因为使用时判断不为空才remove的
int temp = array[front++];
if (front == size)
front = 0;
return temp;
}
}
public class Graph2 {
class Vertex2 {
char label;
boolean visited;
public Vertex2(char label) {
this.label = label;
visited = false;
}
}
private Vertex2[] vertex;
// 小于队列size
private int maxSize;
private int curSize;
private int[][] adjMat;
private Que queue;
public Graph2(int size) {
queue = new Que();
maxSize = size;
vertex = new Vertex2[maxSize];
curSize = 0;
adjMat = new int[maxSize][maxSize];
for (int i = 0; i < maxSize; i++)
for (int j = 0; j < maxSize; j++)
adjMat[i][j] = 0;
}
public void addVer(char label) {
vertex[curSize++] = new Vertex2(label);
}
public void addAdj(int first, int end) {
if (first == end)//不要也可以,自己肯定是visit过的
return;
adjMat[first][end] = 1;
adjMat[end][first] = 1;
}
// 广度优先
public void bfs(int index) {
vertex[index].visited = true;
display(index);
queue.add(index);
int key;
while (!queue.isEmpty()) {
int temp = queue.removeFirst();
while ((key = findUnvisitedAdj(temp)) != -1) {
vertex[key].visited = true;
queue.add(key);
display(key);
}
}
// 重置
for (int i = 0; i < curSize; i++)
vertex[i].visited = false;
}
private int findUnvisitedAdj(int temp) {
for (int i = 0; i < curSize; i++)
if (adjMat[temp][i] == 1 && vertex[i].visited == false)
return i;
return -1;
}
private void display(int index) {
System.out.print(vertex[index].label);
}
public static void main(String[] args) {
Graph2 g2 = new Graph2(10);
g2.addVer('A');
g2.addVer('B');
g2.addVer('C');
g2.addVer('D');
g2.addVer('E');
g2.addVer('F');
g2.addVer('G');
g2.addVer('H');
g2.addVer('I');
g2.addAdj(0, 1);
g2.addAdj(1, 4);
g2.addAdj(1, 5);
g2.addAdj(0, 2);
g2.addAdj(2, 6);
g2.addAdj(0, 3);
g2.addAdj(3, 7);
g2.addAdj(3, 8);
g2.bfs(1);
}
}
输出不太好看,没有路径层次信息。想写个搜索2个点之间所有路径的方法,在DFS里写不出来。。。感觉BFS应该好写些。