图的概念
1.什么是图
图是一种和树相像的数据结构,通常有一个固定的形状,这是有物理或抽象的问题来决定的。
1. 邻接
如果两个顶点被同一条边连接,就成这两个顶点为邻接的。
2. 路径
路径是从一个顶点到另一个顶点经过的边的序列。
3. 连通图和非连通图
至少有一条路径可以连接所有的顶点,那么这个图就是连通的,否则是非连通的。
4. 有向图和无向图
有向图的边是有方向的,如只能从A到B,不能从B到A
无向图的边是没有方向的,可以从A到B,也可以从B到A
5. 带权图
在有些图中,边被赋予了一个权值,权值是一个数字,它可以代表两个顶点的物理距离,或者是一个顶点到另一个顶点的时间等。这样的图叫做带权图。
6. 用程序来实现图
代码实现:
/**
* 顶点类
* @author Administrator
*
*/
public class Vertex {
private char label;
public Vertex(char label) {
this.label = label;
}
}
/**
* 图
* @author Administrator
*
*/
public class Graph {
//顶点数组
private Vertex[] vertexList;
//邻接矩阵
private int[][] adjMat;
//顶点的最大数目
private int maxSize;
//当前顶点
private int nVertex;
public Graph() {
vertexList = new Vertex[maxSize];
adjMat = new int[maxSize][maxSize];
for(int i = 0; i < maxSize; i++) {
for(int j = 0; j < maxSize; j++) {
adjMat[i][j] = 0;
}
}
nVertex = 0;
}
/**
* 添加顶点
*/
public void addVertex(char label) {
vertexList[nVertex++] = new Vertex(label);
}
/**
* 添加边
*/
public void addEdge(int start,int end) {
adjMat[start][end] = 1;
adjMat[end][start] = 1;
}
}
public class TestGraph {
public static void main(String[] args) {
Graph g = new Graph();
g.addVertex('A');
g.addVertex('B');
g.addVertex('C');
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
}
}
图的搜索
1.图的搜索
图的搜索是指从一个指定的顶点可以到达哪些顶点。
1. 搜索的分类:
i. 深度优先搜索DFS
ii. 广度优先搜索BFS
2. 深度优先搜索规则:
a) 如果可能,访问一个邻接的未访问过的顶点,标记它,并把它放入栈中。
b) 如不能执行规则1时,如果栈不能空,就从栈中弹出一个顶点。
c) 当不能执行规则1和规则2时,就完成了整个搜索过程。
3. 深度优先搜索代码实现
4. 广度优先搜索规则:
a) 访问下一个邻接的未访问过的顶点,这个顶点必须是当前节点的邻接点,标记它,并把它插入到队列中。
b) 如果无法执行规则1,那么就从队列头取出一个顶点,并使其作为当前顶点。
c) 当队列为空不能执行规则2时,就完成了整个搜索过程。
代码实现:
/**
* 顶点类
* @author Administrator
*
*/
public class Vertex {
public char label;
public boolean wasVisited;
public Vertex(char label) {
this.label = label;
}
}
public class MyStack {
//底层实现是一个数组
private long[] arr;
private int top;
/**
* 默认的构造方法
*/
public MyStack() {
arr = new long[10];
top = -1;
}
/**
* 带参数构造方法,参数为数组初始化大小
*/
public MyStack(int maxsize) {
arr = new long[maxsize];
top = -1;
}
/**
* 添加数据
*/
public void push(int value) {
arr[++top] = value;
}
/**
* 移除数据
*/
public long pop() {
return arr[top--];
}
/**
* 查看数据
*/
public long peek() {
return arr[top];
}
/**
* 判断是否为空
*/
public boolean isEmpty() {
return top == -1;
}
/**
* 判断是否满了
*/
public boolean isFull() {
return top == arr.length - 1;
}
}
import ch03.MyStack;
/**
* 图
* @author Administrator
*
*/
public class Graph {
//顶点数组
private Vertex[] vertexList;
//邻接矩阵
private int[][] adjMat;
//顶点的最大数目
private int maxSize = 20;
//当前顶点
private int nVertex;
//栈
private MyStack stack;
public Graph() {
vertexList = new Vertex[maxSize];
adjMat = new int[maxSize][maxSize];
for(int i = 0; i < maxSize; i++) {
for(int j = 0; j < maxSize; j++) {
adjMat[i][j] = 0;
}
}
nVertex = 0;
stack = new MyStack();
}
/**
* 添加顶点
*/
public void addVertex(char label) {
vertexList[nVertex++] = new Vertex(label);
}
/**
* 添加边
*/
public void addEdge(int start,int end) {
adjMat[start][end] = 1;
adjMat[end][start] = 1;
}
public int getadjUnvisitedVertex(int v) {
for(int i = 0; i < nVertex; i++) {
if(adjMat[v][i] == 1 && vertexList[i].wasVisited == false) {
return i;
}
}
return -1;
}
public void dfs() {
//首先访问0号顶点
vertexList[0].wasVisited = true;
//显示该顶点
displayVertex(0);
//压入栈中
stack.push(0);
while(!stack.isEmpty()) {
//获得一个未访问过的邻接点
int v = getadjUnvisitedVertex((int)stack.peek());
if(v == -1) {
//弹出一个顶点
stack.pop();
} else {
vertexList[v].wasVisited = true;
displayVertex(v);
stack.push(v);
}
}
//搜索完以后,要将访问信息修改
for(int i = 0; i < nVertex; i++) {
vertexList[i].wasVisited = false;
}
}
public void displayVertex(int v) {
System.out.print(vertexList[v].label);
}
}
public class TestGraph {
public static void main(String[] args) {
Graph g = new Graph();
g.addVertex('A');
g.addVertex('B');
g.addVertex('C');
g.addVertex('D');
g.addVertex('E');
g.addEdge(0, 1);
g.addEdge(1, 2);
g.addEdge(0, 3);
g.addEdge(3, 4);
g.dfs();
}
}
运行结果:
ABCDE
1. 最小生成树
连接每个顶点最少的连线。最小生成树边的数量总是比顶点的数量少1.
代码实现:
/**
* 顶点类
* @author Administrator
*
*/
public class Vertex {
public char label;
public boolean wasVisited;
public Vertex(char label) {
this.label = label;
}
}
public class MyStack {
//底层实现是一个数组
private long[] arr;
private int top;
/**
* 默认的构造方法
*/
public MyStack() {
arr = new long[10];
top = -1;
}
/**
* 带参数构造方法,参数为数组初始化大小
*/
public MyStack(int maxsize) {
arr = new long[maxsize];
top = -1;
}
/**
* 添加数据
*/
public void push(int value) {
arr[++top] = value;
}
/**
* 移除数据
*/
public long pop() {
return arr[top--];
}
/**
* 查看数据
*/
public long peek() {
return arr[top];
}
/**
* 判断是否为空
*/
public boolean isEmpty() {
return top == -1;
}
/**
* 判断是否满了
*/
public boolean isFull() {
return top == arr.length - 1;
}
}
import ch03.MyStack;
/**
* 图
* @author Administrator
*
*/
public class Graph {
//顶点数组
private Vertex[] vertexList;
//邻接矩阵
private int[][] adjMat;
//顶点的最大数目
private int maxSize = 20;
//当前顶点
private int nVertex;
//栈
private MyStack stack;
public Graph() {
vertexList = new Vertex[maxSize];
adjMat = new int[maxSize][maxSize];
for(int i = 0; i < maxSize; i++) {
for(int j = 0; j < maxSize; j++) {
adjMat[i][j] = 0;
}
}
nVertex = 0;
stack = new MyStack();
}
/**
* 添加顶点
*/
public void addVertex(char label) {
vertexList[nVertex++] = new Vertex(label);
}
/**
* 添加边
*/
public void addEdge(int start,int end) {
adjMat[start][end] = 1;
adjMat[end][start] = 1;
}
public int getadjUnvisitedVertex(int v) {
for(int i = 0; i < nVertex; i++) {
if(adjMat[v][i] == 1 && vertexList[i].wasVisited == false) {
return i;
}
}
return -1;
}
public void dfs() {
//首先访问0号顶点
vertexList[0].wasVisited = true;
//显示该顶点
displayVertex(0);
//压入栈中
stack.push(0);
while(!stack.isEmpty()) {
//获得一个未访问过的邻接点
int v = getadjUnvisitedVertex((int)stack.peek());
if(v == -1) {
//弹出一个顶点
stack.pop();
} else {
vertexList[v].wasVisited = true;
displayVertex(v);
stack.push(v);
}
}
//搜索完以后,要将访问信息修改
for(int i = 0; i < nVertex; i++) {
vertexList[i].wasVisited = false;
}
}
public void displayVertex(int v) {
System.out.print(vertexList[v].label);
}
public void mst() {
//首先访问0号顶点
vertexList[0].wasVisited = true;
//压入栈中
stack.push(0);
while(!stack.isEmpty()) {
//当前顶点
int currentVertex = (int)stack.peek();
//获得一个未访问过的邻接点
int v = getadjUnvisitedVertex(currentVertex);
if(v == -1) {
//弹出一个顶点
stack.pop();
} else {
vertexList[v].wasVisited = true;
stack.push(v);
displayVertex(currentVertex);
System.out.print("-");
displayVertex(v);
System.out.print(" ");
}
}
//搜索完以后,要将访问信息修改
for(int i = 0; i < nVertex; i++) {
vertexList[i].wasVisited = false;
}
}
}
public class TestGraph {
public static void main(String[] args) {
Graph g = new Graph();
g.addVertex('A');
g.addVertex('B');
g.addVertex('C');
g.addVertex('D');
g.addVertex('E');
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(0, 3);
g.addEdge(0, 4);
g.addEdge(1, 2);
g.addEdge(1, 3);
g.addEdge(1, 4);
g.addEdge(2, 3);
g.addEdge(2, 4);
g.addEdge(3, 4);
g.mst();
}
}
运行结果:
A-B B-C C-D D-E