图
- 图的创建
/**
* 初始化矩阵和VertexList(用来存放顶点的值)
*
* @param n表示顶点的个数
*/
public Graph(int n) {
VertexList = new ArrayList<String>(n);
edges = new int[n][n];
numOfEdges = 0;
isVisited = new boolean[n];
}
// 插入顶点
public void insertVertex(String vertex) {
VertexList.add(vertex);
}
/**
* 添加边 A = 0;B = 1;C = 2;D = 3; E = 4; 假如A与B相连,则v1 = 0,v2 = 1;weight = 1;
*
* @param v1 第一个顶点的下标
* @param v2 第二个顶点的下标
* @param weight 1表示两点相连
*/
public void insertEdges(int v1, int v2, int weight) {
edges[v1][v2] = weight;
edges[v2][v1] = weight;
numOfEdges++;
}
图的常用方法:
// 返回结点的个数
public int getNumOfVertex() {
return VertexList.size();
}
// 返回边的数目
public int getNumOfEdges() {
return numOfEdges;
}
// 返回对应下标的值 0 => A...
public String getValueByIndex(int index) {
return VertexList.get(index);
}
// 返回v1和v2的weight即表示结点之间有无连接的数
public int getWeight(int v1, int v2) {
return edges[v1][v2];
}
// 显示图的方法即矩阵
public void showGraph() {
for (int[] link : edges) {
System.err.println(Arrays.toString(link));
}
}
- 图的深度优先遍历- - -DFS
思想:一条路走到底,“专一”
深度优先遍历,从初始访问结点出发,初始访问结点可能有多个邻接结点,首先访问第一个邻接结点,再以这个被访问的邻接结点作为作为初始结点,访问它的第一个邻接结点。直至访问完毕。
以此图为例:
对应的邻接矩阵:
代码实现:
// 得到第一个邻接结点的下标
public int getFirstNeighbor(int index) {
for (int j = 0; j < VertexList.size(); j++) {
if (edges[index][j] > 0) {
return j;
}
}
return -1;
}
// 根据前一个邻接结点的下标来获取下一个邻接结点
public int getNextNeighbor(int v1, int v2) {
for (int j = v2 + 1; j < VertexList.size(); j++) {
if (edges[v1][j] > 0) {
return j;
}
}
return -1;
}
// 深度优先遍历算法
// i 第一次就是0
public void dfs(boolean[] isVisted, int i) {
// 首先访问该结点
System.out.print(getValueByIndex(i) + "->");
// 将该结点设置为已访问
isVisted[i] = true;
// 得到当前结点的下一个存在的结点
int w = getFirstNeighbor(i);
while (w != -1) {
// 如果该结点未被访问,则以该结点为起始点进行深度优先搜索
if (!isVisted[w]) {
dfs(isVisted, w);
}
// 如果w结点已经被访问过,继续寻找下一个结点
w = getNextNeighbor(i, w);
}
}
// 对dfs进行重载的方法,遍历所有的结点并进行dfs,解决有非联通图的情况
public void dfs() {
// 遍历所有的结点进行dfs
for (int i = 0; i < getNumOfVertex(); i++) {
if (!isVisited[i]) {
dfs(isVisited, i);
}
}
}
- 广度优先遍历—BFS
思想:“广撒网”
从图的某一结点出发,首先依次访问该结点的所有结点,再按这些结点被访问的先后次序依次访问与它们相邻接的所有未被访问的结点。
代码实现:
public void bfs(boolean[] isVisted, int i) {
// 表示队列头结点的对应下标
int u;
// 邻接结点w
int w;
// 使用队列来记录访问结点的顺序
LinkedList queue = new LinkedList();
// 首先访问该结点
System.out.print(getValueByIndex(i)+"->");
// 将该结点设置为已访问
isVisted[i] = true;
// 将该结点加入队列
queue.addLast(i);
while (!queue.isEmpty()) {
// 取出队列的头结点下标
u = (Integer)queue.removeFirst();
// 得到第一个邻接结点的下标w
w = getFirstNeighbor(u);
while (w != -1) {
// 判断是否访问过
if (!isVisted[w]) {
System.out.print(getValueByIndex(w)+"->");
isVisted[w] = true;
queue.addLast(w);
}
// 以u为前驱结点,找w后面的下一个结点
w = getNextNeighbor(u, w);
}
}
}
public void bfs() {
for (int i = 0; i < getNumOfVertex(); i++) {
if (!isVisited[i]) {
bfs(isVisited, i);
}
}
}