5图
图
1图的概念
- 在图中最基本的单位是顶点,顶点之间的关联关系称为边
- 有些边涉及权重,有权重的图被称为带权图
- 其他还有有向图和无向图
2图的存储方式
2.1邻接矩阵
- 有n个顶点,创建一个n*n的矩阵,矩阵中的每一个元素都代表着从某个顶点到另一个顶点的连接状态
- 其中1表示两顶点之间有关系,0表示两顶点之间没有关系
- 优点:简单直观,可以快速查到一个顶点和另一个顶点之间的关联关系
- 缺点:占用太多空间,不适合稀疏图
//邻接矩阵存储方式
public class MGraph {
private int[][] edges;//邻接矩阵
private int numOfEdges;//边的数目
private int numOfVetex;//顶点的数目
//初始化一个邻接矩阵
public MGraph(int n) {
edges = new int[n][n];
numOfEdges = 0;
numOfVetex = n;
}
//初始化一个邻接矩阵并且以一个n*n的矩阵为其赋值
public MGraph(int[][] edges,int n){
numOfVetex=n;
numOfEdges=0;
this.edges = new int[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
this.edges[i][j]=edges[i][j];
if((edges[i][j]!=-1)&&(edges[i][j]!=0)){
numOfEdges++;
}
}
}
}
public static void main(String args[]){
int[][] edges={{0,2,-1,-1},{-1,0,3,1},{-1,-1,0,4},{5,-1,-1,0}};
MGraph m=new MGraph(edges,4);
}
}
2.2邻接表
- 在邻接表中,图的每一个顶点都是一个链表的头节点,其后连接着该顶点能够直接到达的相邻节点
- 逆邻接表和邻接表正好相反:逆邻接表每一个顶点作为链表的头节点,后继节点所存储的是能够直接到达该顶点的相邻顶点
public class LGraph {
//顶点节点
private class VNode{
int data; //起点的序号
ArcNode firstArc; //指向第一条边
public VNode(int data, ArcNode firstArc) {
this.data = data;
this.firstArc = firstArc;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public ArcNode getFirstArc() {
return firstArc;
}
public void setFirstArc(ArcNode firstArc) {
this.firstArc = firstArc;
}
}
//边节点
private class ArcNode{
int adjvex; //该边指向终点的序号
ArcNode nextarc; //下一条边的指针
int len; //该边的长度
public ArcNode(int adjvex, ArcNode nextarc, int len) {
this.adjvex = adjvex;
this.nextarc = nextarc;
this.len = len;
}
public int getAdjvex() {
return adjvex;
}
public void setAdjvex(int adjvex) {
this.adjvex = adjvex;
}
public ArcNode getNextarc() {
return nextarc;
}
public void setNextarc(ArcNode nextarc) {
this.nextarc = nextarc;
}
public int getLen() {
return len;
}
public void setLen(int len) {
this.len = len;
}
}
ArrayList<VNode> vNodes;
int numOfVetex;
int numOfEdges;
public LGraph() {
vNodes=new ArrayList<VNode>();
numOfVetex=0;
numOfEdges=0;
}
public LGraph(int[][] edges,int n){
numOfVetex=n;
numOfEdges=0;
vNodes=new ArrayList<VNode>();
for(int i=0;i<n;i++){
VNode v=new VNode(i,null);
vNodes.add(v);
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(edges[i][j]!=0&&edges[i][j]!=-1){
ArcNode arc=new ArcNode(j,null,edges[i][j]);
VNode v=vNodes.get(i);
arc.setNextarc(v.getFirstArc());
v.setFirstArc(arc);
numOfEdges++;
}
}
}
//将邻接表存储的图转化为矩阵存储的图
public MGraph toMGraph(){
int[][] edges=new int[numOfVetex][numOfVetex];
for(int i=0;i<vNodes.size();i++){
edges[i][i]=0;
ArcNode arc=vNodes.get(i).getFirstArc();
while(arc!=null){
edges[i][arc.getAdjvex()]=arc.getLen();
arc=arc.getNextarc();
}
}
MGraph m=new MGraph(edges,numOfVetex);
return m;
}
public static void main(String args[]){
int[][] edges={{0,2,-1,-1},{-1,0,3,1},{-1,-1,0,4},{5,-1,-1,0}};
LGraph l=new LGraph(edges,4);
}
}
- 简易版
//图的顶点
private static class Vertex{
int data;
Vertex(int data){
this.data=data;
}
}
//图邻接表形式
private static class Graph{
private int size;//顶点数
private Vertex[] vertexes;//顶点
private LinkedList[] adj;//边
Graph(int size){
this.size=size;
//初始化顶点和邻接表
vertexes=new Vertex[size];
adj=new LinkedList[size];
//防止空指针
for(int i=0;i<size;i++){
vertexes[i]=new Vertex(i);
adj[i]=new LinkedList();
}
}
}
public static void main(String[] args) {
Graph graph=new Graph(3);
graph.adj[0].add(1);
graph.adj[0].add(2);
graph.adj[1].add(2);
graph.adj[2].add(0);
}
3图的遍历
- 深度优先遍历(DFS)和广度优先遍历(BFS)
- 邻接矩阵版
//邻接矩阵
//从某一个顶点开始对该图进行深度优先搜索
public void DFS(int v) {
int[] visited = new int[numOfVetex];
for (int i = 0; i < numOfVetex; i++) {
visited[i] = 0;
}
DFSREC(v, visited);
System.out.println();
int flag=1;
for(int i=0;i<visited.length;i++){
if(visited[i]==0)
{
flag=0;
break;
}
}
if(flag==1)
System.out.println("已遍历完全图");
else
System.out.println("从该点出发无法遍历全图");
}
//深度优先搜索辅助函数
private void DFSREC(int v, int visited[]) {
visited[v] = 1;
System.out.print(v + "-->");
for (int i = 0; i < numOfVetex; i++) {
if (edges[v][i] != -1 && edges[v][i] != 0 && visited[i] != 1) {
DFSREC(i, visited);
}
}
}
//广度优先搜索
public void BFS(int v) {
int[] qu=new int[numOfVetex];
int[] visited=new int[numOfVetex];
int head=0;
int tail=0;
qu[tail++]=v;
visited[v]=1;
while(head!=tail){
int t=qu[head++];
System.out.print(t+"-->");
for(int i=0;i<numOfVetex;i++){
if(edges[t][i]!=-1&&edges[t][i]!=0&&visited[i]==0)
{
qu[tail++]=i;
visited[i]=1;
}
}
}
}
- 邻接表
//邻接表
//深度优先遍历
public static void dfs(Graph graph,int start, boolean[] visited){
System.out.println(graph.vertexes[start].data);
visited[start]=true;
for (Object index : graph.adj[start]){
if (!visited[(int) index]){
dfs(graph, (int) index,visited);
}
}
}
//广度优先遍历
public static void bfs(Graph graph,int start,boolean[] visited,LinkedList<Integer> queue){
queue.offer(start);
while (!queue.isEmpty()){
int front=queue.poll();
if (visited[front]){
continue;
}
System.out.println(graph.vertexes[front].data);
visited[front]=true;
for (Object index:graph.adj[front]){
queue.offer((int)index);
}
}
}

浙公网安备 33010602011771号