123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- package com.yihu.hos.common.graph;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import java.util.*;
- /**
- * 邻接链表(Adjacency List)实现的有向图
- * @param <V>
- */
- public class DGraphImpl<V> implements IDGraph<V> {
- private static Logger logger = LoggerFactory.getLogger(DGraphImpl.class);
- /**
- * 顶点对象,其中有对应的顶点以及从以此顶点为起点的边
- */
- private class VE {
- /**此顶点*/
- private V v;
- /**以此顶点为起点的边的集合,是一个列表,列表的每一项是一条边*/
- private List<Edge<V>> mEdgeList;
-
- /**
- * 构造一个新的顶点对象
- * @param v
- */
- public VE(V v) {
- this.v = v;
- this.mEdgeList = new LinkedList<Edge<V>>();
- }
-
- @Override
- public String toString() {
- String ret = String.format("v : %s , list len : %s",
- v, mEdgeList.size());
- return ret;
- }
-
- /**
- * 将一条边添加到边集合中
- * @param e
- */
- public void addEdge(Edge<V> e) {
- if(getEdge(e.getDest()) == null) {
- mEdgeList.add(e);
- } else {
- logger.warn("edge exist : %s", e);
- }
- }
-
- /**
- * 读取某条边
- * @param dest
- * @return
- */
- public Edge<V> getEdge(V dest) {
- Edge<V> ret = null;
- if(dest != null) {
- for(Edge<V> edge : mEdgeList) {
- if(edge.getDest() != null &&
- dest.equals(edge.getDest())) {
- ret = edge;
- break;
- }
- }
- }
- return ret;
- }
-
- /**
- * 读取某条边
- * @param dest
- * @return
- */
- public Edge<V> removeEdge(V dest) {
- Edge<V> ret = null;
- if(dest != null) {
- for(Edge<V> edge : mEdgeList) {
- if(edge.getDest() != null &&
- dest.equals(edge.getDest())) {
- ret = edge;
- mEdgeList.remove(edge);
- break;
- }
- }
- }
- return ret;
- }
- }
-
- /**
- * 广度优先的迭代器
- */
- public class BFSIterator implements Iterator<V> {
- /**已访问过的顶点列表*/
- private List<V> mVisitList = null;
- /**待访问的顶点队列*/
- private Queue<V> mVQueue = null;
- /**
- * 构造广度优先迭代器
- * @param root
- */
- public BFSIterator(V root) {
- mVisitList = new LinkedList<V>();
- mVQueue = new LinkedList<V>();
- //将初始节点入队列
- 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<Edge<V>> list = ve.mEdgeList;
- for(Edge<V> 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<VE> mVEList;
- /**
- * 构造邻接链表有向图
- */
- public DGraphImpl() {
- mVEList = new LinkedList<VE>();
- }
- @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<V> 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<V> remove(Edge<V> e) {
- Edge<V> 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<V> get(int src, int dest) {
- Edge<V> 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<V> iterator(V root) {
- Iterator<V> ret = null;
- //广度优先的迭代器
- ret = new BFSIterator(root);
- return ret;
- }
- @Override
- public void convertDAG() {
- // TODO Auto-generated method stub
-
- }
- /**
- * 从顶点对象列表中读取输入顶点对应的所有边对象
- * @param v
- * @return
- */
- @Override
- public List<Edge<V>> getEdgeList(V v) {
- List<Edge<V>> 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<V> 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;
- }
- }
|