《Java数据结构跟算法》第二版 Robert lafore 编程作业 第十四章
《Java数据结构和算法》第二版 Robert lafore 编程作业 第十四章
《Java数据结构和算法》第二版 Robert lafore 编程作业 第十四章
/* 14.1 修改path.java(清单14.2),打印一张任意两点间最小耗费的表。这个 练习需要修改原来假设源点总是A的例程。 */ package chap14.pp1; // path.java // demonstrates shortest path with weighted, directed graphs // to run this program: C>java PathApp //////////////////////////////////////////////////////////////// class DistPar // distance and parent { // items stored in sPath array public int distance; // distance from start to this vertex public int parentVert; // current parent of this vertex // ------------------------- public DistPar(int pv, int d) // constructor { distance = d; parentVert = pv; } // ------------------------- } // end class DistPar // ///////////////////////////////////////////////////////////// class Vertex { public char label; // label (e.g. 'A') public boolean isInTree; // ------------------------- public Vertex(char lab) // constructor { label = lab; isInTree = false; } // ------------------------- } // end class Vertex // ////////////////////////////////////////////////////////////// class Graph { private final int MAX_VERTS = 20; private final int INFINITY = 1000000; private Vertex vertexList[]; // list of vertices private int adjMat[][]; // adjacency matrix private int nVerts; // current number of vertices private int nTree; // number of verts in tree private DistPar sPath[]; // array for shortest-path data private int currentVert; // current vertex private int startToCurrent; // distance to currentVert // ------------------------- public Graph() // constructor { vertexList = new Vertex[MAX_VERTS]; // adjacency matrix adjMat = new int[MAX_VERTS][MAX_VERTS]; nVerts = 0; nTree = 0; for (int j = 0; j < MAX_VERTS; j++) // set adjacency for (int k = 0; k < MAX_VERTS; k++) // matrix adjMat[j][k] = INFINITY; // to infinity sPath = new DistPar[MAX_VERTS]; // shortest paths } // end constructor // ------------------------- public void addVertex(char lab) { vertexList[nVerts++] = new Vertex(lab); } // ------------------------- public void addEdge(int start, int end, int weight) { adjMat[start][end] = weight; // (directed) } // ------------------------- public void path() // find all shortest paths { // ============================================== // 编程作业 14.1 // 外层加了个for循环 for (int i = 0; i < nVerts; i++) { int startTree = i; // start at vertex 0 vertexList[startTree].isInTree = true; nTree = 1; // put it in tree // transfer row of distances from adjMat to sPath for (int j = 0; j < nVerts; j++) { int tempDist = adjMat[startTree][j]; sPath[j] = new DistPar(startTree, tempDist); } // until all vertices are in the tree while (nTree < nVerts) { int indexMin = getMin(); // get minimum from sPath int minDist = sPath[indexMin].distance; if (minDist == INFINITY) // if all infinite { // or in tree, System.out.println("There are unreachable vertices"); break; // sPath is complete } else { // reset currentVert currentVert = indexMin; // to closest vert startToCurrent = sPath[indexMin].distance; // minimum distance from startTree is // to currentVert, and is startToCurrent } // put current vertex in tree vertexList[currentVert].isInTree = true; nTree++; adjust_sPath(); // update sPath[] array } // end while(nTree<nVerts) if (nTree == nVerts) { System.out.println("There are all reachable vertices"); } displayPaths(); // display sPath[] contents nTree = 0; // clear tree for (int j = 0; j < nVerts; j++) vertexList[j].isInTree = false; // ============================================== } } // end path() // ------------------------- public int getMin() // get entry from sPath { // with minimum distance int minDist = INFINITY; // assume minimum int indexMin = 0; for (int j = 1; j < nVerts; j++) // for each vertex, { // if it's in tree and if (!vertexList[j].isInTree && // smaller than old one sPath[j].distance < minDist) { minDist = sPath[j].distance; indexMin = j; // update minimum } } // end for return indexMin; // return index of minimum } // end getMin() // ------------------------- public void adjust_sPath() { // adjust values in shortest-path array sPath int column = 1; // skip starting vertex while (column < nVerts) // go across columns { // if this column's vertex already in tree, skip it if (vertexList[column].isInTree) { column++; continue; } // calculate distance for one sPath entry // get edge from currentVert to column int currentToFringe = adjMat[currentVert][column]; // add distance from start int startToFringe = startToCurrent + currentToFringe; // get distance of current sPath entry int sPathDist = sPath[column].distance; // compare distance from start with sPath entry if (startToFringe < sPathDist) // if shorter, { // update sPath sPath[column].parentVert = currentVert; sPath[column].distance = startToFringe; } column++; } // end while(column < nVerts) } // end adjust_sPath() // ------------------------- public void displayPaths() { for (int j = 0; j < nVerts; j++) // display contents of sPath[] { System.out.print(vertexList[j].label + "="); // B= if (sPath[j].distance == INFINITY) System.out.print("inf"); // inf else System.out.print(sPath[j].distance); // 50 char parent = vertexList[sPath[j].parentVert].label; System.out.print("(" + parent + ") "); // (A) } System.out.println(""); } // ------------------------- } // end class Graph // ////////////////////////////////////////////////////////////// public class PathApp { public static void main(String[] args) { Graph theGraph = new Graph(); theGraph.addVertex('A'); // 0 (start) theGraph.addVertex('B'); // 1 theGraph.addVertex('C'); // 2 theGraph.addVertex('D'); // 3 theGraph.addVertex('E'); // 4 theGraph.addEdge(0, 1, 50); // AB 50 theGraph.addEdge(0, 3, 80); // AD 80 theGraph.addEdge(1, 2, 60); // BC 60 theGraph.addEdge(1, 3, 90); // BD 90 theGraph.addEdge(2, 4, 40); // CE 40 theGraph.addEdge(3, 2, 20); // DC 20 theGraph.addEdge(3, 4, 70); // DE 70 theGraph.addEdge(4, 1, 50); // EB 50 System.out.println("Shortest paths"); theGraph.path(); // shortest paths System.out.println(); } // end main() } // end class PathApp // //////////////////////////////////////////////////////////////
/* 14.2 迄今为止已经用邻接矩阵和邻接表实现了图。另一个方法是用Java有引用 代表边,这样Vertex对象就包含一个对其邻接点的引用列表。在有向图中, 这种方式的引用尤其直观。因为它“指明”从一个顶点到另一个顶点。写程 序实现这个表示方法。main()方法应该与path.java程序(清单)的图。然 后,它应该显示图的连通性表,以证明图被正确的构建。还要在某处存储 每条边的权值。一个方法是使用Edge类,类中存储权值和边的终点。每个 顶点拥有一个Edge对象的列表--即,从这个顶点开始的边。 */ package chap14.pp2; import java.util.ArrayList; import java.util.List; // path.java // demonstrates shortest path with weighted, directed graphs // to run this program: C>java PathApp //////////////////////////////////////////////////////////////// class DistPar // distance and parent { // items stored in sPath array public int distance; // distance from start to this vertex public int parentVert; // current parent of this vertex // ------------------------- public DistPar(int pv, int d) // constructor { distance = d; parentVert = pv; } // ------------------------- } // end class DistPar // ///////////////////////////////////////////////////////////// class Vertex { public char label; // label (e.g. 'A') public boolean isInTree; public List<Edge> edges; // list of vertices // ------------------------- public Vertex(char lab) // constructor { label = lab; isInTree = false; edges = new ArrayList<Edge>(); } // 添加边 public void addEdge(Edge edge) { this.edges.add(edge); } // ------------------------- } // end class Vertex // ////////////////////////////////////////////////////////////// class Edge { public int weight; public int end; // 边的终点 public Edge(int weight, int end) { this.weight = weight; this.end = end; } } // ////////////////////////////////////////////////////////////// class Graph { private final int MAX_VERTS = 20; private final int INFINITY = 1000000; private Vertex[] vertexs; private int nVerts; private int nTree; private DistPar sPath[]; // array for shortest-path data private int currentVert; // current vertex private int startToCurrent; // distance to currentVert public Graph() { this.vertexs = new Vertex[MAX_VERTS]; this.sPath = new DistPar[MAX_VERTS]; // shortest paths } public void addEdge(int start, int end, int weight) { Edge edge = new Edge(weight, end); vertexs[start].addEdge(edge); } // ------------------------- public void addVertex(char lab) { vertexs[nVerts++] = new Vertex(lab); } // ------------------------- public void path() // find all shortest paths { for (int k = 0; k < nVerts; k++) { int startTree = k; // start at vertex 0 vertexs[startTree].isInTree = true; nTree = 1; // put it in tree // transfer row of distances from adjMat to sPath List<Edge> edgesList = vertexs[startTree].edges; for (int i = 0; i < MAX_VERTS; i++) { sPath[i] = new DistPar(startTree, INFINITY); } for (int i = 0; i < edgesList.size(); i++) { Edge tempEdge = edgesList.get(i); sPath[tempEdge.end] = new DistPar(startTree, tempEdge.weight); } // until all vertices are in the tree while (nTree < nVerts) { int indexMin = getMin(); // get minimum from sPath int minDist = sPath[indexMin].distance; if (minDist == INFINITY) // if all infinite { // or in tree, System.out.println("There are unreachable vertices"); break; // sPath is complete } else { // reset currentVert currentVert = indexMin; // to closest vert startToCurrent = sPath[indexMin].distance; // minimum distance from startTree is // to currentVert, and is startToCurrent } // put current vertex in tree vertexs[currentVert].isInTree = true; nTree++; adjust_sPath(); // update sPath[] array } // end while(nTree<nVerts) if (nTree == nVerts) { System.out.println("There are all reachable vertices"); } displayPaths(); // display sPath[] contents nTree = 0; // clear tree for (int j = 0; j < nVerts; j++) vertexs[j].isInTree = false; } } // end path() // ------------------------- public int getMin() // get entry from sPath { // with minimum distance int minDist = INFINITY; // assume minimum int indexMin = 0; for (int j = 1; j < nVerts; j++) // for each vertex, { // if it's in tree and if (!vertexs[j].isInTree && // smaller than old one sPath[j].distance < minDist) { minDist = sPath[j].distance; indexMin = j; // update minimum } } // end for return indexMin; // return index of minimum } // end getMin() // ------------------------- public void adjust_sPath() { // adjust values in shortest-path array sPath List<Edge> list = vertexs[currentVert].edges; for (int i = 0; i < list.size(); i++) // go across columns { // if this column's vertex already in tree, skip it int v = list.get(i).end; if (vertexs[v].isInTree) { continue; } // calculate distance for one sPath entry // get edge from currentVert to fringe Edge e = list.get(i); int fringe = e.end; int currentToFringe = e.weight; // add distance from start int startToFringe = startToCurrent + currentToFringe; // get distance of current sPath entry int sPathDist = sPath[fringe].distance; // compare distance from start with sPath entry if (startToFringe < sPathDist) // if shorter, { // update sPath sPath[fringe].parentVert = currentVert; sPath[fringe].distance = startToFringe; } } // end while(column < nVerts) } // end adjust_sPath() // ------------------------- public void displayPaths() { for (int j = 0; j < nVerts; j++) // display contents of sPath[] { System.out.print(vertexs[j].label + "="); // B= if (sPath[j].distance == INFINITY) System.out.print("inf"); // inf else System.out.print(sPath[j].distance); // 50 char parent = vertexs[sPath[j].parentVert].label; System.out.print("(" + parent + ") "); // (A) } System.out.println(""); } // ------------------------- } // end class Graph // ////////////////////////////////////////////////////////////// public class PathApp { public static void main(String[] args) { Graph theGraph = new Graph(); theGraph.addVertex('A'); // 0 (start) theGraph.addVertex('B'); // 1 theGraph.addVertex('C'); // 2 theGraph.addVertex('D'); // 3 theGraph.addVertex('E'); // 4 theGraph.addEdge(0, 1, 50); // AB 50 theGraph.addEdge(0, 3, 80); // AD 80 theGraph.addEdge(1, 2, 60); // BC 60 theGraph.addEdge(1, 3, 90); // BD 90 theGraph.addEdge(2, 4, 40); // CE 40 theGraph.addEdge(3, 2, 20); // DC 20 theGraph.addEdge(3, 4, 70); // DE 70 theGraph.addEdge(4, 1, 50); // EB 50 System.out.println("Shortest paths"); theGraph.path(); // shortest paths System.out.println(); } // end main() } // end class PathApp // //////////////////////////////////////////////////////////////
/* 14.3 实现Floyd算法。可以从path.java程序(清单14.2)开始,适当地修改它。 例如,可以删除所有的最短路径代码。保留对不可到达顶点为无穷大的表示 法。这样作,当比较新得到的耗费和已存在的耗费时,就不再需要检查0。 所有可能到达的路线的耗费都比无穷大小。可以在main()方法中构建任意 复杂的图。 */ package chap14.pp3; // path.java // demonstrates shortest path with weighted, directed graphs // to run this program: C>java PathApp // ///////////////////////////////////////////////////////////// class Vertex { public char label; // label (e.g. 'A') public boolean isInTree; // ------------------------- public Vertex(char lab) // constructor { label = lab; isInTree = false; } public String toString() { return String.valueOf(label); } // ------------------------- } // end class Vertex // ////////////////////////////////////////////////////////////// class Graph { private final int MAX_VERTS = 20; private final int INFINITY = 1000000; private Vertex vertexList[]; // list of vertices private int adjMat[][]; // adjacency matrix private int nVerts; // current number of vertices // ------------------------- public Graph() // constructor { vertexList = new Vertex[MAX_VERTS]; // adjacency matrix adjMat = new int[MAX_VERTS][MAX_VERTS]; nVerts = 0; for (int j = 0; j < MAX_VERTS; j++) // set adjacency for (int k = 0; k < MAX_VERTS; k++) // matrix adjMat[j][k] = INFINITY; // to infinity } // end constructor // ------------------------- public void addVertex(char lab) { vertexList[nVerts++] = new Vertex(lab); } // ------------------------- public void addEdge(int start, int end, int weight) { adjMat[start][end] = weight; // (directed) } // ------------------------- // ========================================================== public void floyd() { for (int i = 0; i < nVerts; i++) { for (int j = 0; j < nVerts; j++) { if (adjMat[i][j] < INFINITY) { for (int k = 0; k < nVerts; k++) { if (adjMat[k][i] < INFINITY) { int temp = adjMat[k][i] + adjMat[i][j]; if (adjMat[k][j] > temp) { adjMat[k][j] = temp; } } } } } } } // ========================================================== // ------------------------- public void display() { for (int i = 0; i < nVerts; i++) { System.out.print(" " + vertexList[i]); } System.out.println(); for (int j = 0; j < nVerts; j++) // display contents of sPath[] { System.out.print(vertexList[j]); for (int i = 0; i < nVerts; i++) { int temp = adjMat[j][i]; if (temp != INFINITY) System.out.print(" " + adjMat[j][i]); else { System.out.print(" "); } } System.out.println(); } System.out.println(); } // ------------------------- } // end class Graph // ////////////////////////////////////////////////////////////// public class PathApp { public static void main(String[] args) { Graph theGraph = new Graph(); theGraph.addVertex('A'); // 0 (start) theGraph.addVertex('B'); // 1 theGraph.addVertex('C'); // 2 theGraph.addVertex('D'); // 3 theGraph.addVertex('E'); // 4 theGraph.addEdge(0, 1, 50); // AB 50 theGraph.addEdge(0, 3, 80); // AD 80 theGraph.addEdge(1, 2, 60); // BC 60 theGraph.addEdge(1, 3, 90); // BD 90 theGraph.addEdge(2, 4, 40); // CE 40 theGraph.addEdge(3, 2, 20); // DC 20 theGraph.addEdge(3, 4, 70); // DE 70 theGraph.addEdge(4, 1, 50); // EB 50 System.out.println("before floyd!"); theGraph.display(); theGraph.floyd(); System.out.println("after floyd!"); theGraph.display(); // shortest paths } // end main() } // end class PathApp // //////////////////////////////////////////////////////////////
/* 14.4 实现本单“难题”中描述的旅行商问题。不考虑它的难度,当N较小时,比 如10或更小,这个问题很好解决。在无向图上尝试一下。使用穷举法测 试每种可能的城市序列。序列改变的方式,参考第6章“递归”中的 anagram.java程序(清单6.2)。用无穷大表示不存在的边。这样做,当 从一个城市到下一个城市的边不存在的情况发生时,不需要中止对序列的 计算;任何无穷大的权值总和都是不可能的路线。而且,不必考虑消除对 称路线的情况,例如ABCDEA和AEDCBA都要显示 */ package chap14.pp4; import java.util.ArrayList; import java.util.List; // path.java // demonstrates shortest path with weighted, directed graphs // to run this program: C>java PathApp // ///////////////////////////////////////////////////////////// class Vertex { public char label; // label (e.g. 'A') public boolean isInTree; // ------------------------- public Vertex(char lab) // constructor { label = lab; isInTree = false; } // ------------------------- } // end class Vertex // ////////////////////////////////////////////////////////////// class Graph { private final int MAX_VERTS = 20; private final int INFINITY = 1000000; private Vertex vertexList[]; // list of vertices private int adjMat[][]; // adjacency matrix private int nVerts; // current number of vertices private int vertexs[]; // array for index of vertex in vertexList private List<int[]> list; // save the possible vertexs[] ; // ------------------------- public Graph() // constructor { vertexList = new Vertex[MAX_VERTS]; // adjacency matrix adjMat = new int[MAX_VERTS][MAX_VERTS]; nVerts = 0; for (int j = 0; j < MAX_VERTS; j++) // set adjacency for (int k = 0; k < MAX_VERTS; k++) // matrix adjMat[j][k] = INFINITY; // to infinity } // end constructor // ------------------------- public void addVertex(char lab) { vertexList[nVerts++] = new Vertex(lab); } // ------------------------- public void addEdge(int start, int end, int weight) { adjMat[start][end] = weight; // (directed) } // ------------------------- // =========================================================== public void displayWord() { int minIndex = 0; int minWeight = INFINITY; for (int i = 0; i < list.size(); i++) { int weight = 0; int[] temp = list.get(i); for (int j = 0; j < temp.length - 1; j++) { weight += adjMat[temp[j]][temp[j + 1]]; } weight += adjMat[temp[temp.length - 1]][temp[0]]; if (weight < minWeight) { minWeight = weight; minIndex = i; } } int[] min = list.get(minIndex); for (int j = 0; j < nVerts; j++) { System.out.print(" " + vertexList[min[j]].label); } System.out.print(" " + vertexList[min[0]].label); System.out.println("(" + minWeight + ")"); } // =========================================================== // 编程作业 14.4 public void travelingSalesman() { vertexs = new int[nVerts]; list = new ArrayList(); for (int i = 0; i < nVerts; i++) { vertexs[i] = i; } doAnagram(vertexs.length); } // =========================================================== public void doAnagram(int newSize) { if (newSize == 1) { // if too small, for (int i = 0; i < nVerts - 1; i++) { if (adjMat[vertexs[i]][vertexs[i + 1]] == INFINITY) { return; } } if (adjMat[vertexs[nVerts - 1]][vertexs[0]] != INFINITY) {// 最后一个顶点到起始点 int[] temp = new int[nVerts]; System.arraycopy(vertexs, 0, temp, 0, nVerts); list.add(temp); } return; } // go no further for (int j = 0; j < newSize; j++) // for each position, { doAnagram(newSize - 1); // anagram remaining rotate(newSize); } } // =========================================================== public void rotate(int newSize) // rotate left all chars from position to end { int j; int position = nVerts - newSize; int temp = vertexs[position]; // save first letter for (j = position + 1; j < nVerts; j++) // shift others left vertexs[j - 1] = vertexs[j]; vertexs[j - 1] = temp; // put first on right } // =========================================================== } // end class Graph // ////////////////////////////////////////////////////////////// public class PathApp { public static void main(String[] args) { Graph theGraph = new Graph(); theGraph.addVertex('A'); // 0 (start) theGraph.addVertex('B'); // 1 theGraph.addVertex('C'); // 2 theGraph.addVertex('D'); // 3 theGraph.addVertex('E'); // 4 theGraph.addEdge(0, 1, 50); // AB 50 theGraph.addEdge(0, 2, 50); // AC 50 theGraph.addEdge(1, 0, 50); // BA 50 theGraph.addEdge(3, 0, 80); // DA 80 theGraph.addEdge(1, 2, 60); // BC 60 theGraph.addEdge(1, 3, 90); // BD 90 theGraph.addEdge(2, 3, 40); // CD 40 theGraph.addEdge(3, 4, 20); // DE 20 theGraph.addEdge(4, 0, 70); // EA 70 theGraph.addEdge(4, 1, 50); // EB 50 theGraph.travelingSalesman(); theGraph.displayWord(); System.out.println("over!"); } // end main() } // end class PathApp // //////////////////////////////////////////////////////////////
/* 14.5 编写程序找到并显示带权无向图的所有汉密尔顿回路。 */ package chap14.pp5; // path.java // demonstrates shortest path with weighted, directed graphs // to run this program: C>java PathApp //////////////////////////////////////////////////////////////// class DistPar // distance and parent { // items stored in sPath array public int distance; // distance from start to this vertex public int parentVert; // current parent of this vertex // ------------------------- public DistPar(int pv, int d) // constructor { distance = d; parentVert = pv; } // ------------------------- } // end class DistPar // ///////////////////////////////////////////////////////////// class Vertex { public char label; // label (e.g. 'A') public boolean isInTree; // ------------------------- public Vertex(char lab) // constructor { label = lab; isInTree = false; } // ------------------------- } // end class Vertex // ////////////////////////////////////////////////////////////// class Graph { private final int MAX_VERTS = 20; private final int INFINITY = 1000000; private Vertex vertexList[]; // list of vertices private int adjMat[][]; // adjacency matrix private int nVerts; // current number of vertices private int vertexs[]; // array for index of vertex in vertexList // ------------------------- public Graph() // constructor { vertexList = new Vertex[MAX_VERTS]; // adjacency matrix adjMat = new int[MAX_VERTS][MAX_VERTS]; nVerts = 0; for (int j = 0; j < MAX_VERTS; j++) // set adjacency for (int k = 0; k < MAX_VERTS; k++) // matrix adjMat[j][k] = INFINITY; // to infinity } // end constructor // ------------------------- public void addVertex(char lab) { vertexList[nVerts++] = new Vertex(lab); } // ------------------------- public void addEdge(int start, int end, int weight) { adjMat[start][end] = weight; // (directed) adjMat[end][start] = weight; // (directed) } // ------------------------- // =========================================================== public void displayWord() { for (int j = 0; j < nVerts; j++) { System.out.print(" " + vertexList[vertexs[j]].label); } System.out.println(" " + vertexList[vertexs[0]].label); } // =========================================================== // 编程作业 14.5 public void travelingSalesman() { vertexs = new int[nVerts]; for (int i = 0; i < nVerts; i++) { vertexs[i] = i; } doAnagram(vertexs.length); } // =========================================================== public void doAnagram(int newSize) { if (newSize == 1) { // if too small, for (int i = 0; i < nVerts - 1; i++) { if (adjMat[vertexs[i]][vertexs[i + 1]] == INFINITY) { return; } } if (adjMat[vertexs[nVerts - 1]][vertexs[0]] != INFINITY) {// 最后一个顶点到起始点 displayWord(); } return; } // go no further for (int j = 0; j < newSize; j++) // for each position, { doAnagram(newSize - 1); // anagram remaining rotate(newSize); } } // =========================================================== public void rotate(int newSize) // rotate left all chars from position to end { int j; int position = nVerts - newSize; int temp = vertexs[position]; // save first letter for (j = position + 1; j < nVerts; j++) // shift others left vertexs[j - 1] = vertexs[j]; vertexs[j - 1] = temp; // put first on right } // =========================================================== } // end class Graph // ////////////////////////////////////////////////////////////// public class PathApp { public static void main(String[] args) { Graph theGraph = new Graph(); theGraph.addVertex('A'); // 0 (start) theGraph.addVertex('B'); // 1 theGraph.addVertex('C'); // 2 theGraph.addVertex('D'); // 3 theGraph.addVertex('E'); // 4 theGraph.addEdge(0, 1, 50); // AB 50 theGraph.addEdge(0, 2, 50); // AC 50 theGraph.addEdge(1, 3, 90); // BD 90 theGraph.addEdge(2, 3, 40); // CD 40 theGraph.addEdge(3, 4, 20); // DE 20 theGraph.addEdge(4, 0, 70); // EA 70 theGraph.addEdge(4, 1, 50); // EB 50 theGraph.travelingSalesman(); theGraph.displayWord(); System.out.println("over!"); } // end main() } // end class PathApp // //////////////////////////////////////////////////////////////