java数据结构_附12_图、顶点和边的定义(双链存储)
图--双链式存储结构 顶点 和 边 的定义
1、Vertex.java
2、Edge.java
3、AbstractGraph.java
1、
public class Vertex {
private Object info;//顶点信息
private LinkedList adjacentEdges;//顶点的邻接边表
private LinkedList reAdjacentEdges;//顶点的逆邻接边表,无向图时为空
private boolean visited;//访问状态
private Node vexPosition;//顶点在顶点表中的位置
private int graphType;//顶点所在图的类型
private Object application;//应用信息。例如求最短路径时为Path,求关键路径时为Vtime
//构造方法:在图G中引入一个新顶点
public Vertex(Graph g, Object info) {
this.info = info;
adjacentEdges = new LinkedListDLNode();
reAdjacentEdges = new LinkedListDLNode();
visited = false;
graphType = g.getType();
vexPosition = g.insert(this);
application = null;
}
//辅助方法:判断顶点所在图的类型
private boolean isUnDiGraphNode(){ return graphType==Graph.UndirectedGraph;}
//获取或设置顶点信息
public Object getInfo(){ return info;}
public void setInfo(Object obj){ this.info = info;}
//与顶点的度相关的方法
public int getDeg(){
if (isUnDiGraphNode())
return adjacentEdges.getSize();//无向图顶点的(出/入)度即为邻接边表的规模
else
return getOutDeg()+getInDeg();//有向图顶点的度为出度与入度之和
}
public int getOutDeg(){
return adjacentEdges.getSize();//有(无)向图顶点的出度为邻接表规模
}
public int getInDeg(){
if (isUnDiGraphNode())
return adjacentEdges.getSize();//无向图顶点的入度就是它的度
else
return reAdjacentEdges.getSize();//有向图顶点入度为逆邻接表的规模
}
//获取与顶点关联的边
public LinkedList getAdjacentEdges(){ return adjacentEdges;}
public LinkedList getReAdjacentEdges(){
if (isUnDiGraphNode())
return adjacentEdges;//无向图顶点无逆邻接边表,其逆邻接边表就是邻接边表
else
return reAdjacentEdges;
}
//取顶点在所属图顶点集中的位置
public Node getVexPosition(){ return vexPosition;}
//与顶点访问状态相关方法
public boolean isVisited(){ return visited;}
public void setToVisited(){ visited = true;}
public void setToUnvisited(){ visited = false;}
//取或设置顶点应用信息
protected Object getAppObj(){ return application;}
protected void setAppObj(Object app){ application = app;}
//重置顶点状态信息
public void resetStatus(){
visited = false;
application = null;
}
}
2、
public class Edge {
public static final int NORMAL = 0;
public static final int MST = 1;//MST边
public static final int CRITICAL = 2;//关键路径中的边
private int weight;//权值
private Object info;//边的信息
private Node edgePosition;//边在边表中的位置
private Node firstVexPosition;//边的第一顶点与第二顶点
private Node secondVexPosition;//在顶点表中的位置
private Node edgeFirstPosition;//边在第一(二)顶点的邻接(逆邻接)边表中的位置
private Node egdeSecondPosition;//在无向图中就是在两个顶点的邻接表中的位置
private int type;//边的类型
private int graphType;//所在图的类型
//构造方法:在图G中引入一条新边,其顶点为u、v
public Edge(Graph g, Vertex u, Vertex v, Object info){
this(g,u,v,info,1);
}
public Edge(Graph g, Vertex u, Vertex v, Object info, int weight) {
this.info = info;
this.weight = weight;
edgePosition = g.insert(this);
firstVexPosition = u.getVexPosition();
secondVexPosition = v.getVexPosition();
type = Edge.NORMAL;
graphType = g.getType();
if (graphType==Graph.UndirectedGraph){
//如果是无向图,边应当加入其两个顶点的邻接边表
edgeFirstPosition = u.getAdjacentEdges().insertLast(this);
egdeSecondPosition = v.getAdjacentEdges().insertLast(this);
}else {
//如果是有向图,边加入起始点的邻接边表,终止点的逆邻接边表
edgeFirstPosition = u.getAdjacentEdges().insertLast(this);
egdeSecondPosition = v.getReAdjacentEdges().insertLast(this);
}
}
//get&set methods
public Object getInfo(){ return info;}
public void setInfo(Object obj){ this.info = info;}
public int getWeight(){ return weight;}
public void setWeight(int weight){ this.weight = weight;}
public Vertex getFirstVex(){ return (Vertex)firstVexPosition.getData();}
public Vertex getSecondVex(){ return (Vertex)secondVexPosition.getData();}
public Node getFirstVexPosition(){ return firstVexPosition;}
public Node getSecondVexPosition(){ return secondVexPosition;}
public Node getEdgeFirstPosition(){ return edgeFirstPosition;}
public Node getEdgeSecondPosition(){ return egdeSecondPosition;}
public Node getEdgePosition(){ return edgePosition;}
//与边的类型相关的方法
public void setToMST(){ type = Edge.MST;}
public void setToCritical(){ type = Edge.CRITICAL;}
public void resetType(){ type = Edge.NORMAL;}
public boolean isMSTEdge(){ return type==Edge.MST;}
public boolean isCritical(){ return type==Edge.CRITICAL;}
}
3、
public abstract class AbstractGraph implements Graph {
protected LinkedList vertexs;//顶点表
protected LinkedList edges;//边表
protected int type;//图的类型
public AbstractGraph(int type){
this.type = type;
vertexs = new LinkedListDLNode();
edges = new LinkedListDLNode();
}
//返回图的类型
public int getType(){
return type;
}
//返回图的顶点数
public int getVexNum() {
return vertexs.getSize();
}
//返回图的边数
public int getEdgeNum() {
return edges.getSize();
}
//返回图的所有顶点
public Iterator getVertex() {
return vertexs.elements();
}
//返回图的所有边
public Iterator getEdge() {
return edges.elements();
}
//添加一个顶点v
public Node insert(Vertex v) {
return vertexs.insertLast(v);
}
//添加一条边e
public Node insert(Edge e) {
return edges.insertLast(e);
}
//判断顶点u、v是否邻接,即是否有边从u到v
public boolean areAdjacent(Vertex u, Vertex v) {
return edgeFromTo(u,v)!=null;
}
//对图进行深度优先遍历
public Iterator DFSTraverse(Vertex v) {
LinkedList traverseSeq = new LinkedListDLNode();//遍历结果
resetVexStatus();//重置顶点状态
DFS(v, traverseSeq);//从v点出发深度优先搜索
Iterator it = getVertex();//从图中未曾访问的其他顶点出发重新搜索
for(it.first(); !it.isDone(); it.next()){
Vertex u = (Vertex)it.currentItem();
if (!u.isVisited()) DFS(u, traverseSeq);
}
return traverseSeq.elements();
}
//深度优先的递归算法
private void DFSRecursion(Vertex v, LinkedList list){
v.setToVisited();
list.insertLast(v);
Iterator it = adjVertexs(v);//取得顶点v的所有邻接点
for(it.first(); !it.isDone(); it.next()){
Vertex u = (Vertex)it.currentItem();
if (!u.isVisited()) DFSRecursion(u,list);
}
}
//深度优先的非递归算法
private void DFS(Vertex v, LinkedList list){
Stack s = new StackSLinked();
s.push(v);
while (!s.isEmpty()){
Vertex u = (Vertex)s.pop();
if (!u.isVisited()){
u.setToVisited();
list.insertLast(u);
Iterator it = adjVertexs(u);
for(it.first(); !it.isDone(); it.next()){
Vertex adj = (Vertex)it.currentItem();
if (!adj.isVisited()) s.push(adj);
}
}//if
}//while
}
//对图进行广度优先遍历
public Iterator BFSTraverse(Vertex v) {
LinkedList traverseSeq = new LinkedListDLNode();//遍历结果
resetVexStatus();//重置顶点状态
BFS(v, traverseSeq);//从v点出发广度优先搜索
Iterator it = getVertex();//从图中未曾访问的其他顶点出发重新搜索
for(it.first(); !it.isDone(); it.next()){
Vertex u = (Vertex)it.currentItem();
if (!u.isVisited()) BFS(u, traverseSeq);
}
return traverseSeq.elements();
}
private void BFS(Vertex v, LinkedList list){
Queue q = new QueueSLinked();
v.setToVisited();
list.insertLast(v);
q.enqueue(v);
while (!q.isEmpty()){
Vertex u = (Vertex)q.dequeue();
Iterator it = adjVertexs(u);
for(it.first(); !it.isDone(); it.next()){
Vertex adj = (Vertex)it.currentItem();
if (!adj.isVisited()){
adj.setToVisited();
list.insertLast(adj);
q.enqueue(adj);
}//if
}//for
}//while
}
//求顶点v到其他顶点的最短路径
public Iterator shortestPath(Vertex v) {
LinkedList sPath = new LinkedListDLNode();
resetVexStatus();//重置图中各顶点的状态信息
Iterator it = getVertex();//初始化,将v到各顶点的最短距离初始化为由v直接可达的距离
for(it.first(); !it.isDone(); it.next()){
Vertex u = (Vertex)it.currentItem();
int weight = Integer.MAX_VALUE;
Edge e = edgeFromTo(v,u);
if (e!=null)
weight = e.getWeight();
if(u==v) weight = 0;
Path p = new Path(weight,v,u);
setPath(u, p);
}
v.setToVisited();//顶点v进入集合S,以visited=true表示属于S,否则不属于S
sPath.insertLast(getPath(v));//求得的最短路径进入链接表
for (int t=1;t<getVexNum();t++){//进行n-1次循环找到n-1条最短路径
Vertex k = selectMin(it);//中间顶点k。可能选出无穷大距离的点,但不会为空
k.setToVisited();//顶点k加入S
sPath.insertLast(getPath(k));//求得的最短路径进入链接表
int distK = getDistance(k);//以k为中间顶点修改v到V-S中顶点的当前最短路径
Iterator adjIt = adjVertexs(k);//取出k的所有邻接点
for(adjIt.first(); !adjIt.isDone(); adjIt.next()){
Vertex adjV = (Vertex)adjIt.currentItem();
Edge e = edgeFromTo(k,adjV);
if ((long)distK+(long)e.getWeight()<(long)getDistance(adjV)){//发现更短的路径
setDistance(adjV, distK+e.getWeight());
amendPathInfo(k,adjV);//以k的路径信息修改adjV的路径信息
}
}//for
}//for(int t=1...
return sPath.elements();
}
//在顶点集合中选择路径距离最小的
protected Vertex selectMin(Iterator it){
Vertex min = null;
for(it.first(); !it.isDone(); it.next()){
Vertex v = (Vertex)it.currentItem();
if(!v.isVisited()){ min = v; break;}
}
for(; !it.isDone(); it.next()){
Vertex v = (Vertex)it.currentItem();
if(!v.isVisited()&&getDistance(v)<getDistance(min))
min = v;
}
return min;
}
//修改到终点的路径信息
protected void amendPathInfo(Vertex mid, Vertex end){
Iterator it = getPath(mid).getPathInfo();
getPath(end).clearPathInfo();
for(it.first(); !it.isDone(); it.next()){
getPath(end).addPathInfo(it.currentItem());
}
getPath(end).addPathInfo(mid.getInfo());
}
//删除一个顶点v
public abstract void remove(Vertex v);
//删除一条边e
public abstract void remove(Edge e);
//返回从u指向v的边,不存在则返回null
public abstract Edge edgeFromTo(Vertex u, Vertex v);
//返回从u出发可以直接到达的邻接顶点
public abstract Iterator adjVertexs(Vertex u);
//求无向图的最小生成树,如果是有向图不支持此操作
public abstract void generateMST() throws UnsupportedOperation;
//求有向图的拓扑序列,无向图不支持此操作
public abstract Iterator toplogicalSort() throws UnsupportedOperation;
//求有向无环图的关键路径,无向图不支持此操作
public abstract void criticalPath() throws UnsupportedOperation;
//辅助方法,重置图中各顶点的状态信息
protected void resetVexStatus(){
Iterator it = getVertex();
for(it.first(); !it.isDone(); it.next()){
Vertex u = (Vertex)it.currentItem();
u.resetStatus();
}
}
//重置图中各边的状态信息
protected void resetEdgeType(){
Iterator it = getEdge();
for(it.first(); !it.isDone(); it.next()){
Edge e = (Edge)it.currentItem();
e.resetType();
}
}
//求最短路径时,对v.application的操作
protected int getDistance(Vertex v){ return ((Path)v.getAppObj()).getDistance();}
protected void setDistance(Vertex v, int dis){ ((Path)v.getAppObj()).setDistance(dis);}
protected Path getPath(Vertex v){ return (Path)v.getAppObj();}
protected void setPath(Vertex v, Path p){ v.setAppObj(p);}
}
java数据结构_附12_图、顶点和边的定义(双链存储)的更多相关文章
- java数据结构_附11_图的接口定义
图的接口定义 Graph public class UnsupportedOperation extends RuntimeException {public UnsupportedOperation ...
- java数据结构_笔记(4)_图
图一.概念.图: 是一种复杂的非线性数据结构.图的二元组定义: 图 G 由两个集合 V 和 E 组成,记为:G=(V, E) 其中: V 是顶点的有穷非空集合,E 是 V 中顶点偶对(称为边)的有穷 ...
- java数据结构_笔记(5)_图的算法
图的算法 1 图的遍历图的遍历就是从图中某个顶点出发,按某种方法对图中所有顶点访问且仅访问一次.遍历算法是求解图的连通性问题.拓扑排序和求关键路径等算法的基础. 2 深度优先遍历从图中某个顶点V 出发 ...
- 13.Java基础_数组内存图
单个数组内存图 new int[3]: 在堆内存里申请一块空间存储int类型的变量(初始化时值都为0) int[] array: 在栈内存申请一块内存存储堆内存里数组的首地址 array[i]: 通过 ...
- 16.Java基础_对象内存图
单个对象 1.进入main函数,生成main函数的栈空间 2.先在mian函数的栈空间里产生一个Student变量(以后会用来存储Studnet对象的首地址),然后进入Student类,在堆内存创建S ...
- java 数据结构 图
以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客,主要是在自己理解的基础上进行记录. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示 ...
- java数据结构----图
1.图:.在计算机程序设计中,图是最常用的数据结构之一.对于存储一般的数据问题,一般用不到图.但对于某些(特别是一些有趣的问题),图是必不可少的.图是一种与树有些相像的数据结构,从数学意义上来讲,树是 ...
- java数据结构----带权图
1.带权图:要引入带权图,首先要引入最小生成树,当所有的边拥有相同的权值时.问题变得简单了,算法可以选择任意一条边加入最小生成树.但是当边有不同的权值时,需要用一些算法决策来选择正确的边. 2.带权图 ...
- java数据结构和算法06(红黑树)
这一篇我们来看看红黑树,首先说一下我啃红黑树的一点想法,刚开始的时候比较蒙,what?这到底是什么鬼啊?还有这种操作?有好久的时间我都缓不过来,直到我玩了两把王者之后回头一看,好像有点儿意思,所以有的 ...
随机推荐
- 猎奇过后,VR还有什么能让用户买单?
VR乍到之时,声如迅雷,来势汹汹却转瞬而逝. 能够在市场激起千层浪,大抵是因其强势地撩起了不少好奇心者,而随着这个热闹周围聚拢层层的围观者,自然吸引了更多人驻足. 但围观之下,好奇心不会转化为购买率. ...
- 百川即时通讯跨appkey问题解决
当前调用的sdk版本为: <script src="https://g.alicdn.com/aliww/??h5.openim.sdk/1.0.6/scripts/wsdk.js,h ...
- 【腾讯云的1001种玩法】腾讯云搭建DiscuzX论坛
版权声明:本文由艾可德原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/506828001481866457 来源:腾云阁 h ...
- 安装pear
下载go-pear.phar php go-pear.phar pear install Mail-1.2.0 pear list
- UI UIBUTTON
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- MySql学习(二) —— where / having / group by / order by / limit 简单查询
注:该MySql系列博客仅为个人学习笔记. 这篇博客主要记录sql的五种子句查询语法! 一个重要的概念:将字段当做变量看,无论是条件,还是函数,或者查出来的字段. select五种子句 where 条 ...
- JVM 虚拟机 内存说明
Java虚拟机所管理的内存图: 1程序计数器: 该模块作用是记录线程执行字节码的位置,记录程序执行状态,以便该线程下次获得CPU时继续执行.程序里的每个线程程序计数器相互独立,互不影响,该内存区也称“ ...
- Android获取屏幕实际高度跟显示高度,判断Android设备是否拥有虚拟功能键
//获取屏幕尺寸,不包括虚拟功能高度 getWindowManager().getDefaultDisplay().getHeight(); 获取屏幕原始尺寸高度,包括虚拟功能键高度, private ...
- 艺萌TCP文件传输及自动更新系统介绍(TCP文件传输)(四)
艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输) 该系统基于开源的networkComms通讯框架,此通讯框架以前是收费的,目前已经免费并开源,作者是英国的,开发时间5年多,框架很稳定. 项 ...
- MICAPS二次开发一些功能调用
1.调用地图并将micaps文件加载地图上 IFileBindingService fbs = ServiceLocator.Current.GetInstance< IFileBindingS ...