/* * 文 件 名: DPGraph.java * 修改时间: 2012-12-25 */ package graph; /** * 有向带权图(边带权) * * @version [版本号, 2012-12-25] */ public class DPGraph { /** * 存储图顶点的数组 */ private Vertex[] vertexArray; /** * 权值矩阵,代表顶点之间的权值,为0表示不可达,行为起始点,列为结束点 */ private double[][] powerArray; /** * 当前顶点数组中得顶点个数 */ private int nVertex; /** * <默认构造函数> */ public DPGraph() { this(10); } /** * <默认构造函数> */ public DPGraph(int capacity) { if (capacity <= 0) { capacity = 10; } vertexArray = new Vertex[capacity]; // 权值矩阵初始化都是0 powerArray = new double[capacity][capacity]; for (int i = 0; i < capacity; i++) { for (int j = 0; j < capacity; j++) { powerArray[i][j] = 0; } } nVertex = 0; } /** * 增加一个图顶点 * * @param label * @see [类、类#方法、类#成员] */ public void addVertex(char label) { // 如果顶点数组满了,扩容一倍 if (nVertex >= vertexArray.length) { Vertex[] tempVertexArray = new Vertex[nVertex * 2]; double[][] tempPowerArray = new double[nVertex * 2][nVertex * 2]; // 顶点复制 System.arraycopy(vertexArray, 0, tempVertexArray, 0, nVertex); // 权值矩阵复制 for (int i = 0; i < nVertex; i++) { System.arraycopy(powerArray[i], 0, tempPowerArray[i], 0, nVertex); } vertexArray = tempVertexArray; powerArray = tempPowerArray; } vertexArray[nVertex++] = new Vertex(label); } /** * 增加一条边,权值默认为1 * * @param start * @param end * @see [类、类#方法、类#成员] */ public void addEdge(int start, int end) { addEdge(start, end, 1); } /** * 增加一条边 * * @param start * @param end * @see [类、类#方法、类#成员] */ public void addEdge(int start, int end, double power) { if (start < 0 || start > nVertex - 1 || end < 0 || end > nVertex - 1) { throw new ArrayIndexOutOfBoundsException(); } powerArray[start][end] = power; } /** * 增加一条边 * * @param start * @param end * @see [类、类#方法、类#成员] */ public void addEdge(char startLabel, int endLabel) { addEdge(startLabel, endLabel, 1); } /** * 增加一条边 * * @param start * @param end * @see [类、类#方法、类#成员] */ public void addEdge(char startLabel, int endLabel, double power) { int start, end; start = end = -1; for (int i = 0; i < nVertex; i++) { if (vertexArray[i].label == startLabel) { start = i; } if (vertexArray[i].label == endLabel) { end = i; } if (start != -1 && end != -1) { break; } } if (start < 0 || start > nVertex - 1 || end < 0 || end > nVertex - 1) { throw new ArrayIndexOutOfBoundsException(); } powerArray[start][end] = power; } /** * 拓扑排序算法,使用顶点数组和权值数组的副本来操作,以免图数据丢失 该算法有个缺陷就是有向图中不能有环(某路径的起点和终点是同一个点) * * @see [类、类#方法、类#成员] */ public void topoSort() { System.out.println("拓扑排序开始..."); if (nVertex > 0) { // 备份图数据 Vertex[] tempVertexArray = new Vertex[nVertex];// 顶点副本 double[][] tempPowerArray = new double[nVertex][nVertex];// 权值矩阵副本 int tempNVertex = nVertex; // 顶点复制 System.arraycopy(vertexArray, 0, tempVertexArray, 0, nVertex); // 权值矩阵复制 for (int i = 0; i < nVertex; i++) { System.arraycopy(powerArray[i], 0, tempPowerArray[i], 0, nVertex); } // 这里做排序操作,需要对原图做删除操作 while (nVertex > 0) { for (int i = 0; i < nVertex; i++) { // 如果某个索引顶点出度为0,则删除该节点 int outDegree = getOutDegree(i); if (outDegree == 0) { // 访问这个顶点 vertexArray[i].visit(); deleteVertex(i); break; } } } // 最后恢复图数据 vertexArray = tempVertexArray; powerArray = tempPowerArray; nVertex = tempNVertex; } System.out.println("拓扑排序结束..."); } /** * 获取一个顶点的出度 * * @param index * 顶点索引如果超过报个运行时异常 * @return * @see [类、类#方法、类#成员] */ public int getOutDegree(int index) { int count = 0; if (index < 0 || index > nVertex - 1) { throw new ArrayIndexOutOfBoundsException(); } for (int i = 0; i < nVertex; i++) { if (powerArray[index][i] != 0) { count++; } } return count; } /** * 删除指定索引的一个顶点 * * @param index * @see [类、类#方法、类#成员] */ public void deleteVertex(int index) { if (index < 0 || index > nVertex - 1) { throw new ArrayIndexOutOfBoundsException(); } // 顶点数组中删除这个顶点 System.arraycopy(vertexArray, index + 1, vertexArray, index, nVertex - index - 1); // 删除权值数组的行 System.arraycopy(powerArray, index + 1, powerArray, index, nVertex - index - 1); // 删除权值数组的列,暂时只能用循环来删除了,不知道有没有更好的方法呢。。 for (int i = 0; i < nVertex - 1; i++) { System.arraycopy(powerArray[i], index + 1, powerArray[i], index, nVertex - index - 1); } nVertex--; } /** * 删除指定标签的一个顶点,只删除找到的第一个 * * @param index * @see [类、类#方法、类#成员] */ public void deleteVertex(char label) { for (int i = 0; i < nVertex; i++) { if (vertexArray[i].label == label) { deleteVertex(i); break; } } } }
数据结构之图(有向带权图)
最新推荐文章于 2024-06-16 23:31:49 发布