无向图就是边全为无序结点对的图
html
注意区分:若是无向图拥有最大数目的连通顶点的边,则无向图是彻底的;若是无向图中任意两个顶点之间都存在一条路径,则认为无向图是连通的。如图是非连通无向图,D与另外三个顶点之间均没有任何路径。
java
无向树是一种连通的无环无向图,其中一个元素被指定为树根node
有向图也称双向图,是一种边为有序顶点对的图,边(A,B)和(B,A)是不一样的有向边
git
如有向图中任意两个顶点之间都存在一条路径,则认为该有向图是连通的。下图中第一个图是连通的,第二个图不是,由于没有任何路径能从其它顶点游历到1,也不能从6出发游历任何其余顶点
算法
无向连通图及以每一个顶点为起点的广度优先遍历
无向非连通图及以每一个顶点为起点的广度优先遍历
数组
问题一解决:经过查找资料其过程可认为:网络
广度优先遍历(使用一个队列):二者之间惟一不一样之处是:深度优先遍历使用栈而不是队列来管理遍历学习
问题二解决:邻接列表是对每一个顶点创建一个链表,表示以改顶点为起点的全部顶点。经过访问一个顶点的链表便可得出该顶点的全部边。由此也可也得出以改顶点为起点的一条路径。
有向图:
一共有1234四个顶点,因此创建四个顶点,以1为起点的有234,以2为起点的只有4,以3为起点的没有,以4为起点的只有3。
无向图:
一共有ABCD四个顶点,创建4个链表。A顶点链接的边是BCD,与B顶点链接的是ABD,与C顶点链接的只有A,与D顶点链接的是AB。测试
问题一:在iteratorBFS方法中,spa
if (!indexIsValid(startIndex)) return resultList.iterator();不清楚iterator方法的做用
在类声明中加入implements Iterable
public interface Iterable<Item>{ Iterator<Item> iterator(); }
在类中实现iterator()方法,返回一个本身定义的迭代器Iterator
public Iterator<Item> iterator(){ //若是须要逆序遍历数组,自定义一个逆序迭代数组的迭代器 return new ReverseArrayIterator(); }
在类中设置内部类(如private class ReverseArrayIterator() ),内部类声明中加入implements Iterator
public interface Iterator { boolean hasNext(); Object next(); void remove(); }
这些是在第四周中学到过的,好比ArrayList类,彻底符合以上步骤。
在这里,因为索引无效,必需要返回一个相同类型的值,实际上就是空的。
问题二解决:见注释
private Iterator<T> iteratorBFS(int startIndex) { Integer x; QueueADT<Integer> traversalQueue = new LinkedQueue<Integer>(); UnorderedListADT<T> resultList = new ArrayUnorderedList<T>(); //索引无效,返回空 if (!indexIsValid(startIndex)) return resultList.iterator(); boolean[] visited = new boolean[maxCount]; //把全部顶点设为false,白色 for (int i = 0; i < maxCount; i++) visited[i] = false; //进入队列的为true,即访问过的,灰色 traversalQueue.enqueue(startIndex); visited[startIndex] = true; while (!traversalQueue.isEmpty()) { //出队列涂黑存入resultList中 x = traversalQueue.dequeue(); resultList.addToRear((T) nodelist.get(x).getElement()); //若是进入resultList的顶点还有相邻的未访问过的顶点,将其涂灰入队 for (int i = 0; i < maxCount; i++) { if (hasEdge(x, i) && !visited[i]) { traversalQueue.enqueue(i); visited[i] = true; Int++; } } } return new GraphIterator(resultList.iterator()); }
//最短路径的顶点集 private Iterator<T> iteratorShortestPath(int startIndex, int targetIndex) { UnorderedListADT<T> resultList = new ArrayUnorderedList<T>(); //若是索引值都无效,返回空 if (!indexIsValid(startIndex) || !indexIsValid(targetIndex)) return resultList.iterator(); //it表示构成startindex和targetindex之间最短路径的顶点集,并存储在resultlist链表中,获取结点集合的迭代器对象 Iterator<Integer> it = iteratorShortestPathIndices(startIndex, targetIndex); while (it.hasNext()) resultList.addToRear((T)nodelist.get(((Integer)it.next())).getElement()); return new GraphIterator(resultList.iterator()); }
//找到最短路径的顶点值 private Iterator<Integer> iteratorShortestPathIndices(int startIndex, int targetIndex) { int index = startIndex; int[] pathLength = new int[maxCount];//路径长度数组 int[] predecessor = new int[maxCount];//前驱结点 QueueADT<Integer> traversalQueue = new LinkedQueue<Integer>(); UnorderedListADT<Integer> resultList = new ArrayUnorderedList<Integer>(); //若是索引无效或起始终点为同一索引,返回空 if (!indexIsValid(startIndex) || !indexIsValid(targetIndex) || (startIndex == targetIndex)) return resultList.iterator(); boolean[] visited = new boolean[maxCount];//访问过为true,染灰 //先标记为都没访问过,染白 for (int i = 0; i < maxCount; i++) visited[i] = false; //将起始值入队标为访问过,染灰 traversalQueue.enqueue(Integer.valueOf(startIndex)); visited[startIndex] = true; pathLength[startIndex] = 0;//路径长度为0 predecessor[startIndex] = -1;//前驱结点为-1位置 //若是还有访问过的灰色,而且未找到目标索引 while (!traversalQueue.isEmpty() && (index != targetIndex)) { index = (traversalQueue.dequeue()).intValue();//出队列染黑,index储存其元素值 //若是有其余结点与index有联系却没有被访问过的,入队染灰 for (int i = 0; i < maxCount; i++) { if (hasEdge(index,i) && !visited[i]) { pathLength[i] = pathLength[index] + 1;//长度加一 predecessor[i] = index;//index为其前驱结点,predecessor中存储最短路径顶点 traversalQueue.enqueue(Integer.valueOf(i));//进队染灰 visited[i] = true; } } } //若是index不是目标索引,返回空 if (index != targetIndex) return resultList.iterator(); StackADT<Integer> stack = new LinkedStack<Integer>(); index = targetIndex; stack.push(Integer.valueOf(index));//目标索引入栈 do {//index不是起始索引值的元素值时,index表示其前驱结点的元素值,将结点的值依次入栈 index = predecessor[index]; stack.push(Integer.valueOf(index)); } while (index != startIndex); while (!stack.isEmpty()) resultList.addToRear(((Integer)stack.pop()));//栈不为空时,弹出结点添加到resultlist链表 return new GraphIndexIterator(resultList.iterator());//resultlist中储存的就是最短路径的顶点集 }
程序中无意的对象引用保持,使得没有明确的释放对象,以至于堆增加再增加,直到没有额外的空间。
网上的解决办法:
选中被运行的类,点击菜单‘run->run...’,选择(x)=Argument标签页下的vm arguments框里
输入 -Xmx800m, 保存运行。
但我没怎么明白具体操做,我认为个人错误多是第三种状况,因而把第一周中inkedStack方法检查了一下,发现方法size,isEmpty,和toString不完善,在其余方法的条件中调用时就有可能出错,修改以后问题解决。
无
谭鑫20172305:谭鑫的博客中最突出的就是他的扩展学习不少,好比Tarjan算法是我没有了解的,能够说很用心了,博客总结的一直很详细,小小的建议就是但愿解释的时候能够分一下层次,一大段一大段的有点难阅读(o´ω`o)ノ
王禹涵20172323:王禹涵的博客总体很好,及哦啊才问题总结详细,有一个问题就是不太明白代码问题二。
关于图的概念有逻辑性,容易理解,可是问题仍是在代码理解上,我以为Java学习不能停留在知识表面,要深刻理解代码,并学会构造才是最终目的。
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | |
---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 |
第一周 | 0/0 | 1/1 | 8/8 |
第二周 | 1163/1163 | 1/2 | 15/23 |
第三周 | 774/1937 | 1/3 | 12/50 |
第四周 | 3596/5569 | 2/5 | 12/62 |
第五周 | 3329/8898 | 2/7 | 12/74 |
第六周 | 4541/13439 | 3/10 | 12/86 |
第七周 | 1740/15179 | 1/11 | 12/97 |
第八周 | 5947/21126 | 1/12 | 12/109 |
第九周 | 7968/29094 | 2/14 | 12/121 |