@yanglt7
2018-10-21T15:49:06.000000Z
字数 15161
阅读 678
数据结构和算法
对于图的定义,需要明确几个注意的地方:
无向边
有向边
简单图
无向完全图
有向完全图
稀疏图和稠密图
有些图的边或弧带有与它相关的数字,这种与图的边或弧相关的数叫做权(Weight),带权的图通常称为网(Network)。
子图
邻接点、度
路径
连通图
连通图的生成树
对称矩阵:n阶矩阵的元满足a[i][j]=a[j][i](0<=i,j<=n)。即从矩阵的左上角到右下角的主对角线为轴,右上角的元与左下角相对应的元全都是相等的。
作用:
顶点数组: | V0 | V1 | V2 | V3 |
---|
~ | V0 | V1 | V2 | V3 |
---|---|---|---|---|
V0 | 0 | 1 | 1 | 1 |
V1 | 1 | 0 | 1 | 0 |
V2 | 1 | 1 | 0 | 1 |
V3 | 1 | 0 | 1 | 0 |
// 邻接矩阵(无向图)
#include <stdio.h>
#define n 4
#define M 4
#define N 4
int main()
{
int i=0, j=0, k=0;
int c;
int Vertex[n];
int a[M][N];
printf("请输入顶点: ,以-1作为结束标志!\n");
scanf("%d", &c);
while( c != -1 )
{
Vertex[++i] = c;
Vertex[i] = '\0';
scanf("%d", &c);
}
printf("请输入顶点之间边的关系: 1表示两个顶点之间有边,0表示两个顶点之间无边。\n");
for( i=0; i < M; i++ )
{
for( j=0; j < N; j++ )
{
printf("%d 和 %d 之间的关系为: ", i, j);
scanf("%d", &a[i][j]);
printf("%d\n", a[i][j]);
}
}
printf("邻接矩阵(无向图)为: \n");
for( i=0; i < M; i++ )
{
for( j=0; j < N; j++ )
{
printf("%d\t", a[i][j]);
k++;
}
if( k%4 == 0 )
{
printf("\n");
}
}
return 0;
}
顶点数组: | V0 | V1 | V2 | V3 |
---|
~ | V0 | V1 | V2 | V3 |
---|---|---|---|---|
V0 | 0 | ∞ | ∞ | 18 |
V1 | 8 | ∞ | 2 | ∞ |
V2 | 4 | ∞ | 0 | ∞ |
V3 | ∞ | ∞ | ∞ | 0 |
下标 | data | first |
---|---|---|
0 | V0 | |
1 | V1 | |
2 | V2 | |
3 | V3 |
// 邻接表(无向图)
#include<stdio.h>
#include<stdlib.h>
#define MAX_VERTEX_NUM 100
typedef struct {
int adjvex; //该边的另一个顶点的位置
struct ArcNode *nextarc; //指向下一条边
} ArcNode;
typedef struct{
int data; // 顶点的值
ArcNode *firstarc; // 指向第一条依附该顶点的边的指针
} VNode, AdjList[MAX_VERTEX_NUM];
typedef struct{
AdjList vertices; //顶点数组
int vexnum, arcnum;
} ALGraph;
//定位函数
int LocateVex(ALGraph G, int v)
{
int i=0;
for( i=0; i < G.vexnum; i++ )
{
if( v == G.vertices[i].data )
return i;
}
}
void CreateUDG( ALGraph G )
{
ArcNode *p,*q;
int i, j, k, v1, v2;
printf("分别输入顶点个数和边的数目:\n");
scanf("%d%d", &G.vexnum, &G.arcnum);
printf("分别输入各个顶点值:\n");
for( i=0; i < G.vexnum; i++ )
{
scanf("%d", &G.vertices[i].data);
G.vertices[i].firstarc = NULL; //初始化
}
printf("分别输入各条边的两个顶点:\n");
for( k=0; k < G.arcnum; k++ )
{
scanf("%d%d", &v1, &v2);
//定位
i = LocateVex(G,v1);
j = LocateVex(G,v2);
//申请一个结点
p = (ArcNode*)malloc(sizeof(ArcNode));
//赋值
p->adjvex = j;
p->nextarc = NULL;
//连接结点
p->nextarc = G.vertices[i].firstarc;
G.vertices[i].firstarc = p;
q = (ArcNode*)malloc(sizeof(ArcNode));
q->adjvex = i;
q->nextarc = NULL;
q->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = q;
}
}
//输出邻接表
void PrintUDG(ALGraph G)
{
int i, j;
for( i=0; i < G.vexnum; i++ )
{
printf("%d:", i);
ArcNode *p;
p = G.vertices[i].firstarc;
while( p != NULL )
{
printf("->%d", p->adjvex);
p = p->nextarc;
}
printf("\n");
}
}
int main()
{
ALGraph G;
CreateUDG(G);
PrintUDG(G);
return 0;
}
下标 | data | first |
---|---|---|
0 | V0 | |
1 | V1 | |
2 | V2 | |
3 | V3 |
下标 | data | first |
---|---|---|
0 | V0 | |
1 | V1 | |
2 | V2 | |
3 | V3 |
data | firstIn | firstOut |
---|
iVex | iLink | jVex | jLink |
---|
下标 | data | first |
---|---|---|
0 | V0 | |
1 | V1 | |
2 | V2 | |
3 | V3 |
顶点数组: | V0 | V1 | V2 | V3 |
---|
边数组 | begin | end | weight |
---|---|---|---|
edges[0] | 0 | 3 | 5 |
edges[1] | 1 | 0 | 4 |
edges[2] | 1 | 2 | 3 |
edges[3] | 2 | 0 | 8 |
// 边集数组
#include <stdio.h>
#define VertexNum 4
#define EdgesNum 4
int main()
{
int i=0, j=0, k=0, n=0, m=0;
int c;
int Vertex[VertexNum];
int Begin[EdgesNum];
int End[EdgesNum];
int Weight[EdgesNum];
// 存储顶点信息
printf("请输入顶点: ,以-1作为结束标志!\n");
scanf("%d", &c);
while( c != -1 )
{
Vertex[++i] = c;
Vertex[i] = '\0';
scanf("%d", &c);
}
// 存储边的begin数值
for( j=0; j < EdgesNum; j++ )
{
printf("请输入第 %d 条边的起点下标begin:\n", j);
scanf("%d", &Begin[j]);
}
// 存储边的end数值
for( k=0; k < EdgesNum; k++ )
{
printf("请输入第 %d 条边的终点下标end:\n", k);
scanf("%d", &End[k]);
}
// 存储边的weight数值
for( n=0; n < EdgesNum; n++ )
{
printf("请输入第 %d 条边的权值weight:\n", n);
scanf("%d", &Weight[n]);
}
// 打印边集数组
printf("边集数组信息为: 起点下标 终点下标 权值\n");
for( m=0; m < EdgesNum; m++ )
{
printf("Edges[%d]\t%d\t %d\t %d\n", m, Begin[m], End[m], Weight[m]);
}
return 0;
}
题目要求
回溯法:一般和递归可以很好的搭配使用,还有深度优先搜索。
// 马踏棋盘算法
#include <stdio.h>
#include <time.h>
#define X 8
#define Y 8
int chess[X][Y];
//找到基于(x,y)位置的下一个可走的位置
int nextxy(int *x, int *y, int count)
{
switch(count)
{
case 0:
if( *x+2<=X-1 && *y-1>=0 && chess[*x+2][*y-1]==0 )
{
*x += 2;
*y -= 1;
return 1;
}
break;
case 1:
if( *x+2<=X-1 && *y+1<=Y-1 && chess[*x+2][*y+1]==0 )
{
*x += 2;
*y += 1;
return 1;
}
break;
case 2:
if( *x+1<=X-1 && *y-2>=0 && chess[*x+1][*y-2]==0 )
{
*x += 1;
*y -= 2;
return 1;
}
break;
case 3:
if( *x+1<=X-1 && *y+2<=Y-1 && chess[*x+1][*y+2]==0 )
{
*x += 1;
*y += 2;
return 1;
}
break;
case 4:
if( *x-2>=0 && *y-1>=0 && chess[*x-2][*y-1]==0 )
{
*x -= 2;
*y -= 1;
return 1;
}
break;
case 5:
if( *x-2>=0 && *y+1<=Y-1 && chess[*x-2][*y+1]==0 )
{
*x -= 2;
*y += 1;
return 1;
}
break;
case 6:
if( *x-1>=0 && *y-2>=0 && chess[*x-1][*y-2]==0 )
{
*x -= 1;
*y -= 2;
return 1;
}
break;
case 7:
if( *x-1>=0 && *y+2<=Y-1 && chess[*x-1][*y+2]==0 )
{
*x -= 1;
*y += 2;
return 1;
}
break;
default:
break;
}
return 0;
}
void print()
{
int i, j;
for( i=0; i < X; i++ )
{
for( j=0; j < Y; j++ )
{
printf("%2d\t", chess[i][j]);
}
printf("\n");
}
printf("\n");
}
//深度优先遍历棋盘
//(x,y)为位置坐标
//tag是标记变量,每走一步,tag+1
int TravelChessBoard(int x, int y, int tag)
{
int x1=x, y1=y, flag=0, count=0;
chess[x][y] = tag;
if( X*Y == tag )
{
//打印棋盘
print();
return 1;
}
//找到马的下一个可走的坐标(x1,y1),如果找到flag=1,否则为0
flag = nextxy(&x1, &y1, count);
while( 0==flag && count<7 )
{
count ++;
flag = nextxy(&x1, &y1, count);
}
while( flag )
{
if( TravelChessBoard(x1, y1, tag+1) )
{
return 1;
}
//找到马的下一个可走的坐标(x1,y1),如果找到flag=1,否则为0
x1 = x;
y1 = y;
count++;
flag = nextxy(&x1, &y1, count);
while( 0==flag && count<7 )
{
count ++;
flag = nextxy(&x1, &y1, count);
}
}
if( 0 == flag )
{
chess[x][y] = 0;
}
return 0;
}
int main()
{
int i, j;
clock_t start, finish;
start = clock();
for( i=0; i < X; i++ )
{
for( j=0; j < Y; j++ )
{
chess[i][j] = 0;
}
}
if( !TravelChessBoard(2, 0, 1) )
{
printf("抱歉,马踏棋盘失败了!\n");
}
finish = clock();
printf("\n本次计算一共耗时: %f秒\n\n", (double)(finish-start)/CLOCKS_PER_SEC);
return 0;
}
~ | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 |
---|---|---|---|---|---|---|---|---|---|
V0 | 0 | 10 | ∞ | ∞ | ∞ | 11 | ∞ | ∞ | ∞ |
V1 | 10 | 0 | 18 | ∞ | ∞ | ∞ | 16 | ∞ | 12 |
V2 | ∞ | 18 | 0 | 22 | ∞ | ∞ | ∞ | ∞ | 8 |
V3 | ∞ | ∞ | 22 | 0 | 20 | ∞ | ∞ | 16 | 21 |
V4 | ∞ | ∞ | ∞ | 20 | 0 | 26 | ∞ | 7 | ∞ |
V5 | 11 | ∞ | ∞ | ∞ | 26 | 0 | 17 | ∞ | ∞ |
V6 | ∞ | 16 | ∞ | ∞ | ∞ | 17 | 0 | 19 | ∞ |
V7 | ∞ | ∞ | ∞ | 16 | 7 | ∞ | 19 | 0 | ∞ |
V8 | ∞ | 12 | 8 | 21 | ∞ | ∞ | ∞ | ∞ | 0 |
// Prim算法生成最小生成树
void MiniSpanTree_Prim(MGraph G)
{
int min, i, j, k;
int adjvex[MAXVEX]; // 保存相关顶点下标
int lowcost[MAXVEX]; // 保存相关顶点间边的权值
lowcost[0] = 0; // V0作为最小生成树的根开始遍历,权值为0
adjvex[0] = 0; // V0第一个加入
// 初始化操作
for( i=0; i < G.numVertexes; i++ )
{
lowcost[i] = G.arc[0][i]; // 将邻接矩阵第0行所有权值先加入数组
adjvex[i] = 0; // 初始化全部先为V0的下标
}
// 真正构造最小生成树的过程
for( i=0; i < G.numVertexes; i++ )
{
min = INFINITY; // 初始化最小权值为65535等不可能数值
j = 1;
k = 0;
// 遍历全部顶点
while( j < G.numVertexes )
{
// 找出lowcost数组已存储的最小权值
if( lowcost[j] != 0 && lowcost[j] < min )
{
min = lowcost[j];
k = j; // 将发现的最小权值的下标存入k,以待使用
}
j++;
}
// 打印当前顶点边中权值最小的边
printf("(%d, %d)", adjvex[k], k);
lowcost[k] = 0; // 将当前顶点的权值设置为0,表示此顶点已经完成任务,进行下一个顶点的遍历
// 邻接矩阵k行逐个遍历全部顶点
for( j=1; j < G.numVertexes; j++ )
{
if( lowcost[j] != 0 && G.arc[k][j] < lowcost[j] )
{
lowcost[j] = G.arc[k][j];
adjvex[j] = k;
}
}
}
}
~ | begin | end | weight |
---|---|---|---|
edges[0] | 4 | 7 | 7 |
edges[1] | 2 | 8 | 8 |
edges[2] | 0 | 1 | 10 |
edges[3] | 0 | 5 | 11 |
edges[4] | 1 | 8 | 12 |
edges[5] | 3 | 7 | 16 |
edges[6] | 1 | 6 | 16 |
edges[7] | 5 | 6 | 17 |
edges[8] | 1 | 2 | 18 |
edges[9] | 6 | 7 | 19 |
edges[10] | 3 | 4 | 20 |
edges[11] | 3 | 8 | 21 |
edges[12] | 2 | 3 | 22 |
edges[13] | 3 | 6 | 24 |
// Kruskal算法生成最小生成树
int Find(int *parent, int f)
{
while( parent[f] > 0 )
{
f = parent[f];
}
return f;
}
void MiniSpanTree_Kruskal(MGraph G)
{
int i, n, m;
Edge edges[MAGEDGE]; // 定义边集数组
int parent[MAXVEX]; // 定义parent数组用来判断边与边是否形成环路
for( i=0; i < G.numVertexes; i++ )
{
parent[i] = 0;
}
for( i=0; i < G.numEdges; i++ )
{
n = Find(parent, edges[i].begin);
m = Find(parent, edges[i].end);
if( n!= m ) // 如果n==m,不满足!
{
parent[n] = m; // 将此边的结尾顶点放入下标为起点的parent数组中,表示此顶点已经在生成树集合中
printf("(%d, %d) %d ", edges[i].begin, edges[i].end, edges[i].weight);
}
}
}
~ | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 |
---|---|---|---|---|---|---|---|---|---|
V0 | 0 | 1 | 5 | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ |
V1 | 1 | 0 | 3 | 7 | 5 | ∞ | ∞ | ∞ | ∞ |
V2 | 5 | 3 | 0 | ∞ | 1 | 7 | ∞ | ∞ | ∞ |
V3 | ∞ | 7 | ∞ | 0 | 2 | ∞ | 3 | ∞ | ∞ |
V4 | ∞ | 5 | 1 | 2 | 0 | 3 | 6 | 9 | ∞ |
V5 | ∞ | ∞ | 7 | ∞ | 3 | 0 | ∞ | 5 | ∞ |
V6 | ∞ | ∞ | ∞ | 3 | 6 | ∞ | 0 | 2 | 7 |
V7 | ∞ | ∞ | ∞ | ∞ | 9 | 5 | 2 | 0 | 4 |
V8 | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ | 7 | 4 | 0 |
D: 0 1 4 7 5 8 10 12 16
P: 0 0 1 4 2 4 3 6 7
final: 1 1 1 1 1 1 1 1 1
// dijkstra算法求最短路径
#define MAXVEX 9
#define INFINITY 65535
typedef int Patharc[MAXVEX]; // 用于存储最短路径下标的数组
typedef int ShortPathTable[MAXVEX]; // 用于存储到各点最短路径的权值和
void ShortestPath_Dijkstra(MGragh G, int V0, Patharc *P, ShortPathTable *D)
{
int v, w, k, min;
int final[MAXVEX]; // final[w] = 1 表示已经求得顶点V0到Vw的最短路径
// 初始化数据
for( v=0; v < G.numVertexes; v++ )
{
final[v] = 0; // 全部顶点初始化为未找到最短路径
(*D)[V] = G.arc[V0][v]; // 将与V0点有连线的顶点加上权值
(*P)[V] = 0; // 初始化路径数组P为0
}
(*D)[V0] = 0; // V0至V0的路径为0
final[V0] = 1; // V0至V0不需要路径
// 开始主循环,每次求得V0到某个v顶点的最短路径
for( v=1; v < G.numVertexes; v++ )
{
min = INFINITY;
for( w=0; w < G.numVertexes; w++ )
{
if( !final[w] && (*D)[w] < min )
{
k = w;
min = (*D)[w];
}
}
final[k] = 1; // 将目前找到的最近的顶点置1
for( w=0; w < G.numVertexes; w++ )
{
// 如果经过v顶点的路径比现在这条路径的长度短的话,更新
if( !final[w] && (min+G.arc[k][w] < (*D)[w]) )
{
(*D)[w] = min + G.arc[k][w]; // 修改当前路径长度
(*p)[w] = k; // 存放前驱顶点
}
}
}
}
// 弗洛伊德算法求最短路径
#define MAXVEX 9
#define INFINITY 65535
typedef int Pathmatirx[MAXVEX][MAXVEX];
typedef int ShortPathTable[MAXVEX][MAXVEX];
void ShortestPath_Floyd(MGraph G, Pathmatirx *P, ShortPathTable *D)
{
int v, w,k;
// 初始化D和P
for( v=0; v < G.numVertexes; v++ )
{
for( w=0; w < G.numVertexes; w++ )
{
(*D)[v][w] = G.matirx[v][w];
(*P)[v][w] = w;
}
}
// 优美的弗洛伊德算法
for( k=0; k < G.numVertexes; k++ )
{
for( v=0; v < G.numVertexes; v++ )
{
if( (*D)[v][w] > (*D)[v][k] + (*D)[k][w] )
{
(*D)[v][w] = (*D)[v][k] + (*D)[k][w];
(*P)[v][w] = (*P)[v][k];
}
}
}
}
下标 | in | data | first |
---|---|---|---|
0 | 0 | C1 | |
1 | 2 | C2 | |
2 | 2 | C3 | |
3 | 2 | C4 | |
4 | 1 | C5 | |
5 | 1 | C6 | |
6 | 3 | C7 | |
7 | 1 | C8 | |
8 | 1 | C9 | |
9 | 2 | C10 | |
10 | 1 | C11 | |
11 | 1 | C12 | |
12 | 0 | C13 | |
13 | 1 | C14 | |
14 | 1 | C15 |
// 拓扑排序算法
// 边表结点声明
typedef struct EdgeNode
{
int adjvex;
struct EdgeNode *next;
} EdgeNode;
typedef struct VertexNode
{
int in; // 顶点入度
int data;
EdgeNode *firstedge;
} VertexNode, AdjList[MAXVEX];
typedef struct
{
AdjList adjList;
int numVertexes, numEdges;
} GraphAdjList, *GraphAdjList;
// 拓扑排序算法
// 若GL无回路,则输出拓扑排序序列并返回OK,否则返回ERROR
Status TopologicalSort(GraphAdjList GL)
{
EdgeNode *e;
int i, k, gettop;
int top = 0; // 用于栈指针下标索引
int count = 0; // 用于统计输出顶点的个数
int *stack; // 用于存储入度为0的顶点
stack = (int *)malloc(GL->numVertexes * sizeof(int));
for( i=0; i < GL->numVertexes; i++ )
{
if( 0 == GL->adjList[i].in )
{
stack[++top] = i; // 将入度为0的顶点下标入栈
}
}
while( 0 != top )
{
gettop = stack[top--]; // 出栈
printf("%d -> ", GL->adjList[gettop].data);
count++;
for( e=GL->adjList[gettop].firstedge; e; e=e->next )
{
k = e->adjvex;
// 注意:下边这个if条件是分析整个程序的要点
// 将k号顶点邻接点的入度为-1,因为它的前驱已经消除
// 接着判断-1后入度是否为0,如果为0则也入栈
if( !(--GL->adjList[k].in) )
{
stack[++top] = k;
}
}
}
if( count < GL->numVertexes ) //如果count小于顶点数,说明存在环
{
return ERROR;
}
else
{
return OK;
}
}
顶点 | C1 | C2 | C3 | C4 | C5 | C6 | C7 | C8 | C9 |
---|---|---|---|---|---|---|---|---|---|
etv | 0 | 6 | 4 | 5 | 7 | 7 | 14 | 12 | 16 |
ltv | 0 | 6 | 6 | 6 | 7 | 8 | 14 | 12 | 16 |
弧 | a1 | a2 | a3 | a4 | a5 | a6 | a7 | a8 | a9 | a10 | a11 |
---|---|---|---|---|---|---|---|---|---|---|---|
ete | 0 | 0 | 0 | 6 | 4 | 5 | 7 | 7 | 7 | 14 | 12 |
lte | 0 | 0 | 2 | 6 | 6 | 6 | 7 | 7 | 8 | 14 | 12 |
下标 | in | data | first |
---|---|---|---|
0 | 0 | C1 | |
1 | 1 | C2 | |
2 | 1 | C3 | |
3 | 1 | C4 | |
4 | 2 | C5 | |
5 | 1 | C6 | |
6 | 1 | C7 | |
7 | 2 | C8 | |
8 | 2 | C9 |
// 关键路径
// 边表结点声明
typedef struct EdgeNode
{
int adjvex;
struct EdgeNode *next;
} EdgeNode;
// 顶点表结点声明
typedef struct VertexNode
{
int in; // 顶点入度
int data;
EdgeNode *firstedge;
} VertexNode, AdjList[MAXVEX];
typedef struct
{
AdjList adjList;
int numVertexes, numEdges;
} GraphAdjList, *GraphAdjList;
int *etv, *ltv;
int *stack2; // 用于存储拓扑序列的栈
int top2; // 用于stack2的栈顶指针
// 拓扑排序算法
// 若GL无回路,则输出拓扑排序序列并返回OK,否则返回ERROR
Status TopologicalSort(GraphAdjList GL)
{
EdgeNode *e;
int i, k, gettop;
int top = 0; // 用于栈指针下标索引
int count = 0; // 用于统计输出顶点的个数
int *stack; // 用于存储入度为0的顶点
stack = (int *)malloc(GL->numVertexes * sizeof(int));
for( i=0; i < GL->numVertexes; i++ )
{
if( 0 == GL->adjList[i].in )
{
stack[++top] = i; // 将度为0的顶点下标入栈
}
}
// 初始化etv都为0
top2 = 0;
etv = (int *)malloc(GL->numVertexes * sizeof(int));
for( i=0; i < GL->numVertexes; i++ )
{
etv[i] = 0;
}
stack2 = (int *)malloc(GL->numVertexes * sizeof(int));
while( 0 != top )
{
gettop = stack[top--]; // 出栈
printf("%d -> ", GL->adjList[gettop].data);
count++;
for( e=GL->adjList[gettop].firstedge; e; e=e->next )
{
k = e->adjvex;
// 注意:下边这个if条件是分析整个程序的要点
// 将k号顶点邻接点的入度为-1,因为它的前驱已经消除
// 接着判断-1后入度是否为0,如果为0则也入栈
if( !(--GL->adjList[k].in) )
{
stack[++top] = k;
}
if( (etv[gettop] + e->weight) > etv[k] )
{
etv[k] = etv[gettop] + e->weight;
}
}
}
if( count < GL->numVertexes ) //如果count小于顶点数,说明存在环
{
return ERROR;
}
else
{
return OK;
}
}
// 关键路径,GL为有向图,输出GL的各项关键活动
void CriticalPath(GraphAdjList GL)
{
EdgeNode *e;
int i, gettop, k, j;
int ete, lte;
// 调用改进后的拓扑排序,求出etv和stack2的值
TopologicalSort(GL);
// 初始化ltv都为汇点的时间
ltv = (int *)malloc(GL->numVertexes * sizeof(int));
for( i=0; i < GL->numVertexes; i++ )
{
ltv[i] = etv[GL->numVertexes - 1];
}
// 从汇点倒过来逐个计算ltv
while( 0 != top2 )
{
gettop = stack2[top2--]; // 注意,第一个出栈是汇点
for( e=GL->adjList[gettop].firstedge; e; e=e->next )
{
k = e->adjvex;
if( ltv[k] - e->weight < ltv[gettop] )
{
ltv[gettop] = ltv[k] - e->weight;
}
}
}
// 通过etv和ltv求ete和lte
for( j=0; j < Gl->numVertexes; j++ )
{
for( e=GL->adjList[j].firstedge; e; e=e->next )
{
k = e->adjvex;
ete = etv[j];
lte = ltv[k] - e->weight;
if( ete == lte )
{
printf("<v%d, v%d> length: %d, ", GL->adjList[j].data, GL->adjList[k].data, e->weight);
}
}
}
}