常见的非线性结构有两种——树和图,在通过了三周对树的学习以后,本周咱们接触了另外一种非线性结构图的相关内容,包括图的概念、图的分类、图的实现方法等。html
protected final int DEFAULT_CAPACITY = 5; protected int numVertices; // 顶点数目 protected boolean[][] adjMatrix; // 布尔值的矩阵,存储顶点之间有无边 protected T[] vertices; // 存储顶点及顶点的value protected int modCount; public Graph() { numVertices = 0; this.adjMatrix = new boolean[DEFAULT_CAPACITY][DEFAULT_CAPACITY]; this.vertices = (T[])(new Object[DEFAULT_CAPACITY]); }
addEdge方法
:此方法用于在顶点之间添加边,添加的方法有两种,一种方法要输入的参数是两个顶点,另外一种方法要输入的参数是两个顶点在邻接矩阵中的索引值。public void addEdge(int index1, int index2) { if (indexIsValid(index1) && indexIsValid(index2)) { adjMatrix[index1][index2] = true; adjMatrix[index2][index1] = true; modCount++; } } // 使用顶点进行添加的方法实质上和上面用索引值添加的方法是同样的,只不过它使用了一个getIndex方法来获取顶点的索引值 public void addEdge(T vertex1, T vertex2) { addEdge(getIndex(vertex1), getIndex(vertex2)); } // getIndex方法经过遍历存放顶点的泛型数组找到顶点的索引值,顶点在泛型数组中的索引值即为它在邻接矩阵中的索引值 public int getIndex(T vertex) { for (int i = 0;i < numVertices;i++){ if (vertices[i] == vertex){ return i; } else{ return -1; } } return -1; }
addVertex方法
:此方法用于向图中添加新的顶点,添加过程当中有两个步骤,一是在泛型数组中添加该顶点,二是在邻接矩阵中增长一行和一列,并把其中全部恰当的位置都设为false。public void addVertex(T vertex) { //当邻接矩阵满了的时候,对其进行扩容 if ((numVertices + 1) == adjMatrix.length) { expandCapacity(); } //步骤一:在泛型数组中添加该顶点 vertices[numVertices] = vertex; //步骤二:把邻接矩阵中的适当位置改成false for (int i = 0; i < numVertices; i++) { adjMatrix[numVertices][i] = false; adjMatrix[i][numVertices] = false; } numVertices++; modCount++; }
expandCapacity方法
:用邻接矩阵实现无向图中的扩容与其余用数组实现的扩容方法不一样,它不只要复制数组,还要对邻接矩阵进行复制和扩容。protected void expandCapacity() { // 建立新的泛型数组和邻接矩阵 T[] largerVertices = (T[])(new Object[vertices.length*2]); boolean[][] largerAdjMatrix = new boolean[vertices.length*2][vertices.length*2]; // 外层循环进行泛型数组的复制,同时协助内层循环进行邻接矩阵的复制 for (int i = 0; i < numVertices; i++) { // 内层循环进行邻接矩阵的复制 for (int j = 0; j < numVertices; j++) { largerAdjMatrix[i][j] = adjMatrix[i][j]; } largerVertices[i] = vertices[i]; } // 将扩容后的两者赋值给原来的泛型数组和邻接矩阵 vertices = largerVertices; adjMatrix = largerAdjMatrix; }
private ArrayList<VerticeNode> vertices; // 用于存储顶点 private int numVertices; // 记录顶点的个数 private int modCount; public LinearGraph(){ numVertices = 0; modCount = 0; a = 0; vertices = new ArrayList<VerticeNode>(); }
@Override public void addVertex(Object vertex) { VerticeNode node = new VerticeNode(vertex); vertices.add(node); modCount++; numVertices++; }
@Override public void removeVertex(Object vertex) { int i = 0; // 将目标顶点删除 while (vertices.get(i).getElement() != vertex){ i++; } vertices.remove(i); // 将顶点以后的列表里的元素前移 for (int j = 0;j < numVertices;j++){ VerticeNode temp = vertices.get(j); while (temp.getNext() != null){ if (temp.getNext().getElement() == vertex){ temp.setNext(temp.getNext().getNext()); } temp = temp.getNext(); } break; } modCount--; numVertices--; }
@Override public void addEdge(Object vertex1, Object vertex2) { // 寻找顶点要被添加的位置 int i = 0; while (vertices.get(i).getElement() != vertex1){ i++; } // 在顶点一的链表末端添加顶点二,在两顶点之间创建边 VerticeNode temp = vertices.get(i); while (temp.getNext() != null){ temp = temp.getNext(); } temp.setNext(new VerticeNode(vertex2)); // 对顶点二的链表进行上述相同操做 int j = 0; while (vertices.get(j).getElement() != vertex2){ j++; } VerticeNode temp1 = vertices.get(j); while (temp1.getNext() != null){ temp1 = temp1.getNext(); } temp1.setNext(new VerticeNode(vertex1)); }
@Override public void removeEdge(Object vertex1, Object vertex2) { // 找到所要删除的顶点的位置 int i = 0; while (vertices.get(i).getElement() != vertex1){ i++; } // 在顶点一的链表中找到顶点二的前驱结点 VerticeNode temp = vertices.get(i); while (temp.getNext().getElement() != vertex2){ temp = temp.getNext(); } // 若是顶点二位于末端,直接将temp的next设为空便可 if (temp.getNext().getNext() == null){ temp.setNext(null); } // 若是顶点二位于中间,将temp的next设置为顶点二的next便可 else { temp.getNext().setNext(temp.getNext().getNext()); } }
VerticeNode
类,直接进行添加就能够了。上周没有测试。java
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 10/10 | 1/1 | 10/10 | |
第二周 | 246/366 | 2/3 | 20/30 | |
第三周 | 567/903 | 1/4 | 10/40 | |
第四周 | 2346/3294 | 2/6 | 20/60 | |
第五周 | 2346/3294 | 2/8 | 30/90 | |
第六周 | 1343/4637 | 2/8 | 20/110 | |
第七周 | 654/5291 | 1/9 | 25/135 | |
第八周 | 2967/8258 | 1/10 | 15/150 | |
第九周 | 2871/11129 | 2/12 | 20/170 |