DGraphImpl.java 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. package com.yihu.hos.common.graph;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import java.util.*;
  5. /**
  6. * 邻接链表(Adjacency List)实现的有向图
  7. * @param <V>
  8. */
  9. public class DGraphImpl<V> implements IDGraph<V> {
  10. private static Logger logger = LoggerFactory.getLogger(DGraphImpl.class);
  11. /**
  12. * 顶点对象,其中有对应的顶点以及从以此顶点为起点的边
  13. */
  14. private class VE {
  15. /**此顶点*/
  16. private V v;
  17. /**以此顶点为起点的边的集合,是一个列表,列表的每一项是一条边*/
  18. private List<Edge<V>> mEdgeList;
  19. /**
  20. * 构造一个新的顶点对象
  21. * @param v
  22. */
  23. public VE(V v) {
  24. this.v = v;
  25. this.mEdgeList = new LinkedList<Edge<V>>();
  26. }
  27. @Override
  28. public String toString() {
  29. String ret = String.format("v : %s , list len : %s",
  30. v, mEdgeList.size());
  31. return ret;
  32. }
  33. /**
  34. * 将一条边添加到边集合中
  35. * @param e
  36. */
  37. public void addEdge(Edge<V> e) {
  38. if(getEdge(e.getDest()) == null) {
  39. mEdgeList.add(e);
  40. } else {
  41. logger.warn("edge exist : %s", e);
  42. }
  43. }
  44. /**
  45. * 读取某条边
  46. * @param dest
  47. * @return
  48. */
  49. public Edge<V> getEdge(V dest) {
  50. Edge<V> ret = null;
  51. if(dest != null) {
  52. for(Edge<V> edge : mEdgeList) {
  53. if(edge.getDest() != null &&
  54. dest.equals(edge.getDest())) {
  55. ret = edge;
  56. break;
  57. }
  58. }
  59. }
  60. return ret;
  61. }
  62. /**
  63. * 读取某条边
  64. * @param dest
  65. * @return
  66. */
  67. public Edge<V> removeEdge(V dest) {
  68. Edge<V> ret = null;
  69. if(dest != null) {
  70. for(Edge<V> edge : mEdgeList) {
  71. if(edge.getDest() != null &&
  72. dest.equals(edge.getDest())) {
  73. ret = edge;
  74. mEdgeList.remove(edge);
  75. break;
  76. }
  77. }
  78. }
  79. return ret;
  80. }
  81. }
  82. /**
  83. * 广度优先的迭代器
  84. */
  85. public class BFSIterator implements Iterator<V> {
  86. /**已访问过的顶点列表*/
  87. private List<V> mVisitList = null;
  88. /**待访问的顶点队列*/
  89. private Queue<V> mVQueue = null;
  90. /**
  91. * 构造广度优先迭代器
  92. * @param root
  93. */
  94. public BFSIterator(V root) {
  95. mVisitList = new LinkedList<V>();
  96. mVQueue = new LinkedList<V>();
  97. //将初始节点入队列
  98. mVQueue.offer(root);
  99. }
  100. @Override
  101. public boolean hasNext() {
  102. if(mVQueue.size() > 0) {
  103. return true;
  104. } else {
  105. return false;
  106. }
  107. }
  108. @Override
  109. public V next() {
  110. //1.取队列元素
  111. V v = mVQueue.poll();
  112. if(v != null) {
  113. //2.将此元素的邻接边中对应顶点入队列,这些顶点需要符合以下条件:
  114. //1)没访问过;
  115. //2)不在队列中;
  116. VE ve = getVE(v);
  117. if(ve != null) {
  118. List<Edge<V>> list = ve.mEdgeList;
  119. for(Edge<V> edge : list) {
  120. V dest = edge.getDest();
  121. if(!VinList(dest, mVisitList.iterator()) &&
  122. !VinList(dest, mVQueue.iterator())) {
  123. mVQueue.offer(dest);
  124. }
  125. }
  126. }
  127. //3.将此顶点添加到已访问过的顶点列表中
  128. mVisitList.add(v);
  129. }
  130. //4.返回出队列的元素
  131. return v;
  132. }
  133. @Override
  134. public void remove() {
  135. // 暂时不实现
  136. }
  137. }
  138. /**顶点列表,由于会经常进行插入删除,使用链表队列*/
  139. private LinkedList<VE> mVEList;
  140. /**
  141. * 构造邻接链表有向图
  142. */
  143. public DGraphImpl() {
  144. mVEList = new LinkedList<VE>();
  145. }
  146. @Override
  147. public int add(V v) {
  148. int index = -1;
  149. if(v != null) {
  150. VE ve = new VE(v);
  151. mVEList.add(ve);
  152. index = mVEList.indexOf(ve);
  153. }
  154. return index;
  155. }
  156. @Override
  157. public void add(Edge<V> e) {
  158. if(e != null) {
  159. VE ve = getVE(e.getSource());
  160. if(ve != null) {
  161. //若边的起点已经在列表里,则直接将其添加到对应的顶点对象中
  162. ve.addEdge(e);
  163. } else {
  164. //否则提示错误
  165. logger.error("Error, can't find v : %s", e.getSource());
  166. }
  167. }
  168. }
  169. @Override
  170. public V remove(V v) {
  171. V ret = null;
  172. VE ve = removeVE(v);
  173. if(ve != null) {
  174. ret = ve.v;
  175. }
  176. removeRelateEdge(v);
  177. return ret;
  178. }
  179. @Override
  180. public Edge<V> remove(Edge<V> e) {
  181. Edge<V> ret = null;
  182. if(e != null) {
  183. VE ve = getVE(e.getSource());
  184. if(ve != null) {
  185. ret = ve.removeEdge(e.getDest());
  186. }
  187. }
  188. return ret;
  189. }
  190. @Override
  191. public V get(int index) {
  192. V ret = null;
  193. if(index >=0 && index < mVEList.size()) {
  194. VE ve = mVEList.get(index);
  195. if(ve != null) {
  196. ret = ve.v;
  197. }
  198. }
  199. return ret;
  200. }
  201. @Override
  202. public Edge<V> get(int src, int dest) {
  203. Edge<V> ret = null;
  204. V s = get(src);
  205. V d = get(dest);
  206. if(s != null && d != null) {
  207. VE ve = getVE(s);
  208. if(ve != null) {
  209. ret = ve.getEdge(d);
  210. }
  211. }
  212. return ret;
  213. }
  214. @Override
  215. public Iterator<V> iterator(V root) {
  216. Iterator<V> ret = null;
  217. //广度优先的迭代器
  218. ret = new BFSIterator(root);
  219. return ret;
  220. }
  221. @Override
  222. public void convertDAG() {
  223. // TODO Auto-generated method stub
  224. }
  225. /**
  226. * 从顶点对象列表中读取输入顶点对应的所有边对象
  227. * @param v
  228. * @return
  229. */
  230. @Override
  231. public List<Edge<V>> getEdgeList(V v) {
  232. List<Edge<V>> edgeList = new ArrayList<>();
  233. VE ret = null;
  234. if(v != null) {
  235. for(VE ve : mVEList) {
  236. if(ve.v != null && v.equals(ve.v)) {
  237. ret = ve;
  238. break;
  239. }
  240. }
  241. }
  242. if (ret != null) {
  243. return ret.mEdgeList;
  244. }
  245. return edgeList;
  246. }
  247. //////////////////////////////私有方法//////////////////////////////
  248. /**
  249. * 从顶点对象列表中读取输入顶点对应的对象
  250. * @param v
  251. * @return
  252. */
  253. public VE getVE(V v) {
  254. VE ret = null;
  255. if(v != null) {
  256. for(VE ve : mVEList) {
  257. if(ve.v != null && v.equals(ve.v)) {
  258. ret = ve;
  259. break;
  260. }
  261. }
  262. }
  263. return ret;
  264. }
  265. /**
  266. * 从顶点对象列表中删除输入顶点对应的对象
  267. * @param v
  268. * @return 删除的顶点对象
  269. */
  270. private VE removeVE(V v) {
  271. VE ret = null;
  272. if(v != null) {
  273. for(VE ve : mVEList) {
  274. if(ve.v != null && v.equals(ve.v)) {
  275. ret = ve;
  276. mVEList.remove(ve);
  277. break;
  278. }
  279. }
  280. }
  281. return ret;
  282. }
  283. /**
  284. * 删除以某个点作为重点的边
  285. * @param v
  286. */
  287. private void removeRelateEdge(V v) {
  288. if(v != null) {
  289. for(VE ve : mVEList) {
  290. ve.removeEdge(v);
  291. }
  292. }
  293. }
  294. /**
  295. * 判断某个端点是否在某个列表里
  296. * @param v
  297. * @param it
  298. * @return
  299. */
  300. private boolean VinList(V v, Iterator<V> it) {
  301. boolean ret = false;
  302. if(v != null && it != null) {
  303. while(it.hasNext()) {
  304. V v_temp = it.next();
  305. if(v_temp != null && v_temp.equals(v)) {
  306. ret = true;
  307. break;
  308. }
  309. }
  310. }
  311. return ret;
  312. }
  313. }