图邻接表 和 括扑排序

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));
		}
	}
}


        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值