1. 图的邻接表:
图的邻接表表示指对图的每一个顶点Vi 建立一个邻接关系的单链表,表头向量表示该顶点,链表点表示与该顶点相邻接的其他顶点。邻接表适用于 稀疏表
package com.Graph;
/**
* 邻接表 表示稀疏图的表*/
public class Graph {
public int Vertex;
public int EdgeNum;
VNode[] graph;
/**
* V 存放 顶点的编号* E 所有的边
* vertex 顶点与顶点之间的边 weight:vertex中对应的边的权重
* @param V
* @param E
* @param vertex
* @param weight
*/
public Graph(int V[],int E,int [][]vertex,int [] weight)
{
this.Vertex=V.length;
this.EdgeNum=E;
this.graph=new VNode[this.Vertex];
CreateGraph(graph, vertex, weight, V);
}
public void CreateGraph (VNode [] graph,int [][] vertex,int [] weight,int VNum[])
{
// 初始化 邻接表
for(int i=0;i<this.Vertex;i++)
{
graph[i]=new VNode(VNum[i]);
}
// 根据边数建立邻接表
for(int i=0;i<this.EdgeNum;i++)
{
for(int j=0;j<this.Vertex;j++)
{
// 这个只是建立 有向图 邻接表
if(vertex[i][0]==graph[j].Vertexnum)
{
addEdge(graph[j],vertex[i][1],weight[i]);
}
}
for(int j=0;j<this.Vertex;j++)
{
// 加上下面代码 建立无向图的 邻接表
if(vertex[i][1]==graph[j].Vertexnum)
{
addEdge(graph[j],vertex[i][0],weight[i]);
}
}
}
}
/**
* 新边 插入到 邻接表中
* */
private void addEdge(VNode vNode, int ver, int weg) {
EdgeNode pNext=vNode.firstedge;
EdgeNode newEdge=new EdgeNode(ver, weg);
if(pNext==null)
vNode.firstedge=newEdge;
else
{
// 往下遍历
while(pNext.nextedge!=null)
pNext=pNext.nextedge;
pNext.nextedge=newEdge;
}
}
public static void main(String[] args) {
int [][]array={{1,2},{1,3},{1,4},{2,4},{2,3},{3,4}};
int weight[]={1,2,3,4,5,6};
int [] VNum={1,2,3,4};
Graph graph=new Graph(VNum, weight.length, array, weight);
PrintGraph(graph);
}
/**
* 打印图
* */
public static void PrintGraph(Graph graph)
{
for(int i=0;i<graph.Vertex;i++)
{
System.out.print(graph.graph[i].Vertexnum+"--->");
PrintEdge(graph.graph[i].firstedge,graph.graph[i].Vertexnum);
System.out.println();
}
}
private static void PrintEdge(EdgeNode edge,int ver) {
while(edge!=null)
{
System.out.print("["+ver+","+edge.adjvex+","+edge.Weight+"]"+" ");
edge=edge.nextedge;
}
}
/**
* 邻接表头信息
* 所有顶点和 指向下一条边
* */
private class VNode{
int Vertexnum;
EdgeNode firstedge=null;
public VNode(int v)
{
this.Vertexnum=v;
}
}
/**
* 邻接表中 边的信息
* */
private class EdgeNode {
int Weight;
int adjvex;// 相邻顶点的 编号
boolean flag=false;// 此点是否被访问
EdgeNode nextedge=null;
public EdgeNode(int v,int w) {
this.adjvex=v;
this.Weight=w;
}
}
}
二. 括扑排序:有向无环图的一种排序方法
有向边<v,w> 表明 先完成V 的事物才能继续完成w 的事物,计算图中 入度为零的点的排列的顺序
在编码过程中邻接表和初始的入度数组,遍历入度数组将 入度为零压入queue的容器中,将 此顶点及其他顶点相邻边从图中去掉,更新 入度的数组,同时在更新同时将入度为零的表压入到队列中。
package com.Graph;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class TopSort {
public int [] Indegree;
public void getIndegree(Graph graph)
{
int vertnum=graph.Vertex;
Indegree=new int[vertnum+1];//开始原顶点从1 开始的
for(int i=0;i<graph.Vertex;i++)
{
count(graph.graph[i],Indegree);
}
}
private void count(VNode vNode, int[] indegree2) {
EdgeNode next=vNode.firstedge;
while(next!=null)
{
indegree2[next.adjvex]++;
next=next.nextedge;
}
}
public void Print()
{
for(int i=1;i<Indegree.length;i++)
{
System.out.print(Indegree[i]+" ");
}
}
public static void main(String[] args) throws Exception {
int [][]array={{1,2},{1,3},{1,4},{2,4},{2,3},{3,4}};
int weight[]={1,2,3,4,5,6};
int [] VNum={1,2,3,4};
Graph graph=new Graph(VNum, weight.length, array, weight);
TopSort topSort=new TopSort();
topSort.getIndegree(graph);
topSort.topSort(graph);
}
/**
* 扩展排序 ,将 入度为0 顶点 放入到 容器中
* @throws Exception
* */
public void topSort(Graph graph) throws Exception
{
Queue<VNode> queue=new LinkedList<VNode>();
ArrayList<Integer> list=new ArrayList<>();
int counter=0;
for(int i=1;i<Indegree.length;i++)
if(Indegree[i]==0)
queue.add(graph.graph[i-1]);//邻接表中 存储下标从1 开始的
while(!queue.isEmpty())
{
// 将此顶点与其相邻的边的 入度减一
VNode vNode=queue.poll();
list.add(vNode.Vertexnum);
counter++;
EdgeNode next=vNode.firstedge;
while(next!=null)
{
if(Indegree[next.adjvex]>0 &&(--Indegree[next.adjvex])==0)
queue.add(graph.graph[next.adjvex-1]);
next=next.nextedge;
}
}
// 判断回路中是否有环
if(counter!=graph.Vertex)
{
throw new Exception(" 回路中有环");
}
else
{
for(int i=0;i<list.size();i++)
System.out.print(list.get(i));
}
}
}