一、 图的定义
图G由两个集合V和E组成,记为G=(V,E),其中, V是顶点(数据元素)的有穷非空集合,E是V中顶点偶对的有穷集合,这些顶点偶对称为边 。
(1)图的种类:
- 有向图
- 无向图
(2)权和网:
权:图中的边可标上具有某种含义的数值,该数值称为边上的权。
网:权可表示为从一个顶点到另一顶点的距离或耗费,这种边带权的图称网(网络)。
二、 图的存储表示
- 邻接矩阵(矩阵上的每个坐标代表当前两个顶点之间是否有边,有边值为1,无边为0)
- 邻接表(对于图G中的每个顶点vi,把所有邻接于vi的顶点链成一个单链表,这个单链表就称为顶点vi的邻接表)
(1)邻接矩阵:
例如:
对应的邻接矩阵为:
(2)邻接表:
例如:
对应的邻接表为:
(3)邻接表与邻接矩阵对比:
三、图的遍历
- 广度优先搜索算法
- 深度优先搜索算法
(1)连通图的深度优先搜索遍历:
从图中的某个顶点V出发,访问此节点,然后依次从V的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V路径想通的顶点都被访问到。
(2)图的广度优先搜索遍历图:
从图中的某个顶点V出发,并在访问此顶点之后依次访问V的所有未被访问过的邻接点,之后按这些顶点被访问的先后次序依次访问它们的邻接点,直至图中所有和V有路径相通的顶点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
四、 java实现
import java.util.NoSuchElementException;
import java.util.Stack;
public class Graph {
Vertex vertexs[];
int count;
int maxsize;
public Graph(){
count = 0;
maxsize = 50;
vertexs = new Vertex[maxsize];
}
/**
* 向图中添加一个顶点
* @param string
*/
public void addVertex(String string){
vertexs[count] = new Vertex(count, string);
count++;
}
/**
* 指定两个顶点之间添加一条边
* @param a
* @param b
*/
public void addEdge(String a, String b) throws NoSuchElementException{
Vertex vertex1 = null;
Vertex vertex2 = null;
for(int i = 0; i<count; i++){
if(vertexs[i].item.equals(a)){
vertex1 = vertexs[i];
}
if(vertexs[i].item.equals(b)){
vertex2 = vertexs[i];
}
}
if(vertex1 == null || vertex2 == null){
throw new NoSuchElementException();
}
vertex1.list.addLast(vertex2.mark);
vertex2.list.addLast(vertex1.mark);
}
/**
* 图的广度优先搜索算法
* @param string
*/
public void breadthFirstSearch(String string) throws NoSuchElementException{
MyQueue<Integer> queue = new MyQueue<>();
int start = -1;
for(int i = 0; i<count; i++){
if(vertexs[i].item.equals(string)){
start = vertexs[i].mark;
}
}
if(start == -1){
throw new NoSuchElementException("广度优先");
}
System.out.print(vertexs[start].item + " ");
vertexs[start].isVisited = true;
queue.add(start);
while(!queue.isEmpty()){
int temp = 0;
try {
temp = queue.poll();
} catch (EmptyQueueException e) {
e.printStackTrace();
}
MyList<Integer> list = vertexs[temp].list;
Node<Integer> node = list.getFirst();
while(node != null){
int j = node.item;
if(vertexs[j].isVisited == false){
System.out.print(vertexs[j].item + " ");
vertexs[j].isVisited = true;
queue.add(j);
}
node = node.next;
}
}
System.out.println();
setVisited();
}
/**
* 深度优先搜索算法
* @param string
*/
public void depthFirstSearch(String string) throws NoSuchElementException{
Stack<Node<Integer>> stack = new Stack<>();
int start = -1;
for(int i = 0; i<count; i++){
if(vertexs[i].item.equals(string)){
start = vertexs[i].mark;
}
}
if(start == -1){
throw new NoSuchElementException("深度优先");
}
System.out.print(vertexs[start].item + " ");
vertexs[start].isVisited = true;
Node<Integer> node = vertexs[start].list.getFirst();
stack.push(node);
while(!stack.isEmpty()){
while(node != null){
int temp = node.item;
if(vertexs[temp].isVisited == false){
System.out.print(vertexs[temp].item + " ");
vertexs[temp].isVisited = true;
node = vertexs[temp].list.getFirst();
stack.push(node);
}else{
node = stack.pop();
node = node.next;
if(node != null){
stack.push(node);
}
}
}
if(!stack.isEmpty()){
node = stack.pop();
node = node.next;
if(node != null){
stack.push(node);
}
}
}
System.out.println();
setVisited();
}
/**
* 将图内所有元素设置为初始状态
*/
private void setVisited(){
for(int i = 0; i<count; i++){
vertexs[i].isVisited = false;
}
}
/**
* 内部节点
* @author dell
*
*/
class Vertex{
int mark;
String item;
boolean isVisited = false;
MyList<Integer> list = new MyList<>();
public Vertex(Integer mark, String element) {
this.mark = mark;
this.item = element;
}
}
}