package com.yihu.hos.common.graph; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; /** * 邻接链表(Adjacency List)实现的有向图 * @param */ public class DGraphImpl implements IDGraph { private static Logger logger = LoggerFactory.getLogger(DGraphImpl.class); /** * 顶点对象,其中有对应的顶点以及从以此顶点为起点的边 */ private class VE { /**此顶点*/ private V v; /**以此顶点为起点的边的集合,是一个列表,列表的每一项是一条边*/ private List> mEdgeList; /** * 构造一个新的顶点对象 * @param v */ public VE(V v) { this.v = v; this.mEdgeList = new LinkedList>(); } @Override public String toString() { String ret = String.format("v : %s , list len : %s", v, mEdgeList.size()); return ret; } /** * 将一条边添加到边集合中 * @param e */ public void addEdge(Edge e) { if(getEdge(e.getDest()) == null) { mEdgeList.add(e); } else { logger.warn("edge exist : %s", e); } } /** * 读取某条边 * @param dest * @return */ public Edge getEdge(V dest) { Edge ret = null; if(dest != null) { for(Edge edge : mEdgeList) { if(edge.getDest() != null && dest.equals(edge.getDest())) { ret = edge; break; } } } return ret; } /** * 读取某条边 * @param dest * @return */ public Edge removeEdge(V dest) { Edge ret = null; if(dest != null) { for(Edge edge : mEdgeList) { if(edge.getDest() != null && dest.equals(edge.getDest())) { ret = edge; mEdgeList.remove(edge); break; } } } return ret; } } /** * 广度优先的迭代器 */ public class BFSIterator implements Iterator { /**已访问过的顶点列表*/ private List mVisitList = null; /**待访问的顶点队列*/ private Queue mVQueue = null; /** * 构造广度优先迭代器 * @param root */ public BFSIterator(V root) { mVisitList = new LinkedList(); mVQueue = new LinkedList(); //将初始节点入队列 mVQueue.offer(root); } @Override public boolean hasNext() { if(mVQueue.size() > 0) { return true; } else { return false; } } @Override public V next() { //1.取队列元素 V v = mVQueue.poll(); if(v != null) { //2.将此元素的邻接边中对应顶点入队列,这些顶点需要符合以下条件: //1)没访问过; //2)不在队列中; VE ve = getVE(v); if(ve != null) { List> list = ve.mEdgeList; for(Edge edge : list) { V dest = edge.getDest(); if(!VinList(dest, mVisitList.iterator()) && !VinList(dest, mVQueue.iterator())) { mVQueue.offer(dest); } } } //3.将此顶点添加到已访问过的顶点列表中 mVisitList.add(v); } //4.返回出队列的元素 return v; } @Override public void remove() { // 暂时不实现 } } /**顶点列表,由于会经常进行插入删除,使用链表队列*/ private LinkedList mVEList; /** * 构造邻接链表有向图 */ public DGraphImpl() { mVEList = new LinkedList(); } @Override public int add(V v) { int index = -1; if(v != null) { VE ve = new VE(v); mVEList.add(ve); index = mVEList.indexOf(ve); } return index; } @Override public void add(Edge e) { if(e != null) { VE ve = getVE(e.getSource()); if(ve != null) { //若边的起点已经在列表里,则直接将其添加到对应的顶点对象中 ve.addEdge(e); } else { //否则提示错误 logger.error("Error, can't find v : %s", e.getSource()); } } } @Override public V remove(V v) { V ret = null; VE ve = removeVE(v); if(ve != null) { ret = ve.v; } removeRelateEdge(v); return ret; } @Override public Edge remove(Edge e) { Edge ret = null; if(e != null) { VE ve = getVE(e.getSource()); if(ve != null) { ret = ve.removeEdge(e.getDest()); } } return ret; } @Override public V get(int index) { V ret = null; if(index >=0 && index < mVEList.size()) { VE ve = mVEList.get(index); if(ve != null) { ret = ve.v; } } return ret; } @Override public Edge get(int src, int dest) { Edge ret = null; V s = get(src); V d = get(dest); if(s != null && d != null) { VE ve = getVE(s); if(ve != null) { ret = ve.getEdge(d); } } return ret; } @Override public Iterator iterator(V root) { Iterator ret = null; //广度优先的迭代器 ret = new BFSIterator(root); return ret; } @Override public void convertDAG() { // TODO Auto-generated method stub } /** * 从顶点对象列表中读取输入顶点对应的所有边对象 * @param v * @return */ @Override public List> getEdgeList(V v) { List> edgeList = new ArrayList<>(); VE ret = null; if(v != null) { for(VE ve : mVEList) { if(ve.v != null && v.equals(ve.v)) { ret = ve; break; } } } if (ret != null) { return ret.mEdgeList; } return edgeList; } //////////////////////////////私有方法////////////////////////////// /** * 从顶点对象列表中读取输入顶点对应的对象 * @param v * @return */ public VE getVE(V v) { VE ret = null; if(v != null) { for(VE ve : mVEList) { if(ve.v != null && v.equals(ve.v)) { ret = ve; break; } } } return ret; } /** * 从顶点对象列表中删除输入顶点对应的对象 * @param v * @return 删除的顶点对象 */ private VE removeVE(V v) { VE ret = null; if(v != null) { for(VE ve : mVEList) { if(ve.v != null && v.equals(ve.v)) { ret = ve; mVEList.remove(ve); break; } } } return ret; } /** * 删除以某个点作为重点的边 * @param v */ private void removeRelateEdge(V v) { if(v != null) { for(VE ve : mVEList) { ve.removeEdge(v); } } } /** * 判断某个端点是否在某个列表里 * @param v * @param it * @return */ private boolean VinList(V v, Iterator it) { boolean ret = false; if(v != null && it != null) { while(it.hasNext()) { V v_temp = it.next(); if(v_temp != null && v_temp.equals(v)) { ret = true; break; } } } return ret; } }