BFSGraph.java 9.4 KB

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