文章目录
- 一、更新ALGraph
-
- 四、关键路径
-
- (一)、定义
- (二)、Java代码
-
- 1. 由邻接表获取各个顶点入度
- 2. 基于邻接表的拓扑排序
- 3. 关键路径算法
- 4. 源码
- 5. 输出样例
一、更新ALGraph
(一)、Java代码
package graph;
public class ALGraph {
public VexNode[] vexs;
ArcNode[] arcs;
int vexNum, arcNum;
static class Info {
String value;
int weight;
public Info(String value) {
this.value = value;
}
public Info(int weight) {
this.weight = weight;
}
public Info(String value, int weight) {
this.value = value;
this.weight = weight;
}
public String toString() {
return this.value + "=" + this.weight;
}
}
class ArcNode {
int index;
Info info;
ArcNode nextNode;
}
class VexNode {
String data;
ArcNode firstArc;
}
static class Edge {
String start;
String end;
Info info;
public Edge(String start, String end, Info info) {
this.start = start;
this.end = end;
this.info = new Info(info.value, info.weight);
}
}
public ALGraph(String[] vertexs, Edge[] edges) {
vexs = new VexNode[vertexs.length];
arcs = new ArcNode[edges.length];
vexNum = vertexs.length;
arcNum = edges.length;
for (int i = 0; i < vexs.length; i++) {
vexs[i] = new VexNode();
vexs[i].data = vertexs[i];
vexs[i].firstArc = null;
}
for (int i = 0; i < edges.length; i++) {
String start = edges[i].start;
String end = edges[i].end;
int indexOfStart = indexOfVex(start);
int indexOfEnd = indexOfVex(end);
ArcNode arcNode = new ArcNode();
arcNode.index = indexOfEnd;
arcNode.info = edges[i].info;
linkedLast(indexOfStart, arcNode);
arcs[i] = arcNode;
}
}
public int indexOfVex(String v) {
for (int i = 0; i < vexs.length; i++) {
if (vexs[i].data == v)
return i;
}
return -1;
}
public void linkedLast(int indexofstart, ArcNode arcnode) {
if (vexs[indexofstart].firstArc == null) {
vexs[indexofstart].firstArc = arcnode;
} else {
ArcNode tempNode = vexs[indexofstart].firstArc;
while (tempNode.nextNode != null) {
tempNode = tempNode.nextNode;
}
tempNode.nextNode = arcnode;
}
}
public void printALGraphByChar() {
System.out.println("邻接表存储的图:");
for (int i = 0; i < vexs.length; i++) {
System.out.print(vexs[i].data + "----->");
if (vexs[i].firstArc != null) {
ArcNode tempNode = vexs[i].firstArc;
while (tempNode.nextNode != null) {
System.out.print(vexs[tempNode.index].data + "--->");
tempNode = tempNode.nextNode;
}
System.out.print(vexs[tempNode.index].data);
} else {
System.out.print("NULL");
}
System.out.println();
}
}
public void printALGraphByIndex() {
System.out.println("邻接表存储的图:");
for (int i = 0; i < vexs.length; i++) {
System.out.print(i + "----->");
if (vexs[i].firstArc != null) {
ArcNode tempNode = vexs[i].firstArc;
while (tempNode.nextNode != null) {
System.out.print(tempNode.index + "--->");
tempNode = tempNode.nextNode;
}
System.out.print(tempNode.index);
} else {
System.out.print("NULL");
}
System.out.println();
}
}
public static void main(String[] args) {
String[] vexs = { "A", "B", "C", "D", "E" };
Edge[] edges = {
new Edge("A", "B", new Info("权值", 10)),
new Edge("A", "D", new Info("权值", 10)),
new Edge("B", "A", new Info("权值", 20)),
new Edge("B", "C", new Info("权值", 20)),
new Edge("B", "E", new Info("权值", 20)),
new Edge("C", "B", new Info("权值", 30)),
new Edge("C", "D", new Info("权值", 30)),
new Edge("C", "E", new Info("权值", 30)),
new Edge("D", "A", new Info("权值", 40)),
new Edge("D", "C", new Info("权值", 40)),
new Edge("E", "B", new Info("权值", 50)),
new Edge("E", "C", new Info("权值", 50))
};
ALGraph algraph = new ALGraph(vexs, edges);
algraph.printALGraphByChar();
algraph.printALGraphByIndex();
}
}
四、关键路径
(一)、定义
- 与AOV-网相对应的是AOE-网,即边表示活动的网。
- AOE-网,是有向无环图。顶点表示事件,弧表示活动。权表示活动持续时间。
- AOE-网通常用来估算工程的完成时间,以及哪些活动是影响工程进展的关键。
- 路径长度:路径上各活动持续时间的总和(即路径上所有权之和)。
- 完成工程的最短时间:从工程开始点(源点:入度为零,只有一个)到完成点(汇点:出度为零,只有一个)的最长路径称为完成工程的最短时间。
- 关键路径:路径长度最长的路径称为关键路径。
(二)、Java代码
1. 由邻接表获取各个顶点入度
public int[] getInDegrees() {
int[] inDegrees = new int[vexNum];
for (int i = 0; i < vexNum; i++) {
ArcNode arcNode = null;
for (int j = 0; j < vexNum; j++) {
ArcNode tempNode = vexs[j].firstArc;
while (tempNode != null) {
inDegrees[tempNode.index]++;
arcNode = tempNode.nextNode;
tempNode = arcNode;
}
}
}
for (int i = 0; i < vexNum; i++) {
inDegrees[i] /= vexNum;
}
return inDegrees;
}
2. 基于邻接表的拓扑排序
public boolean topoSort() {
System.out.println("拓扑排序(基于邻接表):");
int count = 0;
int[] inDegrees = getInDegrees();
for(int i=0; i<inDegrees.length; i++) {
if(inDegrees[i] == 0) {
stack.push(i);
}
}
while(!stack.isEmpty()) {
int index = stack.pop();
count++;
System.out.print(vexs[index].data + " ");
ArcNode tempNode = vexs[index].firstArc;
while(tempNode != null) {
int nextIndex = tempNode.index;
ve[nextIndex] = Math.max(ve[nextIndex], ve[index]+tempNode.info.weight);
inDegrees[nextIndex]--;
if(inDegrees[nextIndex] == 0) {
stack.push(nextIndex);
}
tempNode = tempNode.nextNode;
}
}
return count == vexNum;
}
3. 关键路径算法
public void criticalPath() {
if(!isTopo()) {
throw new RuntimeException("是个环装图,没有关键路径");
}
for(int i=0; i<ve.length; i++) {
vl[i] = ve[ve.length - 1];
}
while(!viewStack.isEmpty()) {
int index = viewStack.pop();
ArcNode tempNode = vexs[index].firstArc;
while(tempNode != null) {
int nextIndex = tempNode.index;
vl[index] = Math.min(vl[index], vl[nextIndex]-tempNode.info.weight);
tempNode = tempNode.nextNode;
}
}
int arcCount = 0;
for(int i=0; i<vexNum; i++) {
ArcNode tempNode = vexs[i].firstArc;
while(tempNode != null) {
int index = tempNode.index;
ee[arcCount] = ve[i];
el[arcCount] = vl[index] - tempNode.info.weight;
arcCount++;
tempNode = tempNode.nextNode;
}
}
System.out.print("关键事件:");
for(int i=0;i<vexNum-1;i++){
if(vl[i]==ve[i]){
System.out.print(vexs[i].data + "----->");
}
}
if(vl[vexNum-1] == ve[vexNum-1]) {
System.out.print(vexs[vexNum-1].data);
} else {
System.out.print("NULL");
}
System.out.println();
System.out.print("关键活动:");
for(int i=0;i<arcNum;i++){
if(ee[i]==el[i]){
System.out.print(" " + arcs[i].info.toString() + " ");
}
}
System.out.println();
}
4. 源码
package graph;
import java.util.Stack;
public class CriticalPath extends ALGraph {
int[] ve;
int[] vl;
int[] ee;
int[] el;
Stack<Integer> stack = new Stack<Integer>();
Stack<Integer> viewStack = new Stack<Integer>();
public CriticalPath(String[] vertexs, Edge[] edges) {
super(vertexs, edges);
ve = new int[vertexs.length];
vl = new int[vertexs.length];
ee = new int[edges.length];
el = new int[edges.length];
}
public int[] getInDegrees() {
int[] inDegrees = new int[vexNum];
for (int i = 0; i < vexNum; i++) {
ArcNode arcNode = null;
for (int j = 0; j < vexNum; j++) {
ArcNode tempNode = vexs[j].firstArc;
while (tempNode != null) {
inDegrees[tempNode.index]++;
arcNode = tempNode.nextNode;
tempNode = arcNode;
}
}
}
for (int i = 0; i < vexNum; i++) {
inDegrees[i] /= vexNum;
}
return inDegrees;
}
public int[] getOutDegrees() {
int[] outDegrees = new int[vexNum];
int out = 0;
ArcNode vexNode = null;
for (int i = 0; i < vexNum; i++) {
ArcNode tempNode = vexs[i].firstArc;
while (tempNode != null) {
out++;
vexNode = tempNode.nextNode;
tempNode = vexNode;
}
outDegrees[i] = out;
out = 0;
}
return outDegrees;
}
public boolean topoSort() {
System.out.println("拓扑排序(基于邻接表):");
int count = 0;
int[] inDegrees = getInDegrees();
for(int i=0; i<inDegrees.length; i++) {
if(inDegrees[i] == 0) {
stack.push(i);
}
}
while(!stack.isEmpty()) {
int index = stack.pop();
count++;
System.out.print(vexs[index].data + " ");
ArcNode tempNode = vexs[index].firstArc;
while(tempNode != null) {
int nextIndex = tempNode.index;
ve[nextIndex] = Math.max(ve[nextIndex], ve[index]+tempNode.info.weight);
inDegrees[nextIndex]--;
if(inDegrees[nextIndex] == 0) {
stack.push(nextIndex);
}
tempNode = tempNode.nextNode;
}
}
return count == vexNum;
}
public boolean isTopo() {
int count = 0;
int[] inDegrees = getInDegrees();
for(int i=0; i<inDegrees.length; i++) {
if(inDegrees[i] == 0) {
stack.push(i);
viewStack.push(i);
}
}
while(!stack.isEmpty()) {
int index = stack.pop();
count++;
ArcNode tempNode = vexs[index].firstArc;
while(tempNode != null) {
int nextIndex = tempNode.index;
ve[nextIndex] = Math.max(ve[nextIndex], ve[index]+tempNode.info.weight);
inDegrees[nextIndex]--;
if(inDegrees[nextIndex] == 0) {
stack.push(nextIndex);
viewStack.push(nextIndex);
}
tempNode = tempNode.nextNode;
}
}
return count == vexNum;
}
public void criticalPath() {
if(!isTopo()) {
throw new RuntimeException("是个环装图,没有关键路径");
}
for(int i=0; i<ve.length; i++) {
vl[i] = ve[ve.length - 1];
}
while(!viewStack.isEmpty()) {
int index = viewStack.pop();
ArcNode tempNode = vexs[index].firstArc;
while(tempNode != null) {
int nextIndex = tempNode.index;
vl[index] = Math.min(vl[index], vl[nextIndex]-tempNode.info.weight);
tempNode = tempNode.nextNode;
}
}
int arcCount = 0;
for(int i=0; i<vexNum; i++) {
ArcNode tempNode = vexs[i].firstArc;
while(tempNode != null) {
int index = tempNode.index;
ee[arcCount] = ve[i];
el[arcCount] = vl[index] - tempNode.info.weight;
arcCount++;
tempNode = tempNode.nextNode;
}
}
System.out.print("关键事件:");
for(int i=0;i<vexNum-1;i++){
if(vl[i]==ve[i]){
System.out.print(vexs[i].data + "----->");
}
}
if(vl[vexNum-1] == ve[vexNum-1]) {
System.out.print(vexs[vexNum-1].data);
} else {
System.out.print("NULL");
}
System.out.println();
System.out.print("关键活动:");
for(int i=0;i<arcNum;i++){
if(ee[i]==el[i]){
System.out.print(" " + arcs[i].info.toString() + " ");
}
}
System.out.println();
}
public static void main(String[] args) {
String[] vexs = { "V0", "V1", "V2", "V3", "V4", "V5", "V6", "V7", "V8", "V9" };
Edge[] edges = {
new Edge("V0", "V1", new Info("a0", 3)),
new Edge("V0", "V2", new Info("a1", 4)),
new Edge("V1", "V3", new Info("a2", 5)),
new Edge("V1", "V4", new Info("a3", 6)),
new Edge("V2", "V3", new Info("a4", 8)),
new Edge("V2", "V5", new Info("a5", 7)),
new Edge("V3", "V4", new Info("a6", 3)),
new Edge("V4", "V6", new Info("a7", 9)),
new Edge("V4", "V7", new Info("a8", 4)),
new Edge("V5", "V7", new Info("a9", 6)),
new Edge("V6", "V9", new Info("a10", 2)),
new Edge("V7", "V8", new Info("a11", 5)),
new Edge("V8", "V9", new Info("a12", 3))
};
CriticalPath AOE = new CriticalPath(vexs, edges);
AOE.printALGraphByChar();
System.out.println("是否无环:" + AOE.isTopo());
AOE.criticalPath();
}
}
5. 输出样例