목차
머리말
n 노드가 있는 연결된 그래프의 스패닝 트리는 원래 그래프의 모든 n 노드를 포함하고 그래프를 연결 상태로 유지하는 가장 적은 수의 간선을 갖는 원래 그래프의 최소 연결 하위 그래프입니다. 최소 스패닝 트리는 크루스칼(Kruskal) 알고리즘 또는 프라임(Prime) 알고리즘으로 얻을 수 있다.
여기에서는 주로 Prim의 알고리즘과 그 구현 과정에 대한 아이디어를 설명합니다.
1. 최소 스패닝 트리는 무엇입니까?
주어진 무향 그래프 G = (V, E)에서 (u, v)는 정점 u와 정점 v(ie)를 연결하는 간선을 나타내고 w(u, v)는 T가 있는 경우 이 간선의 가중치를 나타냅니다. E의 부분집합이고 비순환 그래프이므로 모든 노드를 연결하는 w(T)가 가장 작은 경우 이 T는 G의 최소 스패닝 트리입니다.
2. Prim의 알고리즘 아이디어
1) 입력: 가중 연결된 그래프, 정점 집합은 V이고 가장자리 집합은 E
2) 초기화: Vnew = {x}, 여기서 x는 집합 V의 노드(시작점), Enew = { }, is empty;
3) Vnew = V가 될 때까지 다음 작업을 반복합니다:
a. 세트 E에서 가중치가 가장 작은 에지 <u, v>를 선택합니다. v는 집합 Vnew에 없고, v∈V(위 조건을 만족하는, 즉 가중치가 같은 간선이 여러 개 있으면 그 중 임의로 하나를 선택할 수 있음), b. 집합 Vnew에 v를 더하고
, 세트 Enew Middle에 <u, v> 에지를 추가합니다
.4) 출력: Vnew 및 Enew 세트를 사용하여 결과 최소 스패닝 트리를 설명합니다.
3. Geng Guohua 교사의 구체적인 구현 단계
이 알고리즘을 구현하기 위해 U에서 VU까지 최소 비용으로 에지를 기록하도록 보조 배열 closedge[]를 설정합니다.
closedge[v]는 adjvex와 lowcost의 두 필드를 포함합니다. 여기서 lowcost는 가장 작은 간선의 가중치를 기록하고 adjvex는 U에서 가장 작은 간선의 정점을 기록합니다.
struct {
int adjvex;
int lowcost;
}closedge[MAX];
3.1 알고리즘 아이디어
1. 먼저 U에 초기 v0을 더하고 나머지 정점 i 각각에 대해 i에서 v0까지의 에지 정보로 closedge[i]를 초기화합니다.
2. v0은 검색을 완료할 필요가 없기 때문에 n-1회 루프를 수행하고 다음 처리를 수행합니다.
3. 각 최소 모서리 closedge[] 세트에서 가장 작은 가장 작은 모서리 closedge[v]를 선택합니다.
4. U에 v를 추가, 여기서 추가는 closedge[v].lowcost=0;
5. 나머지 최소 에지 정보 업데이트 closedge[i]
6. i를 중심으로 하는 에지 그룹의 경우 새 에지의 가중치 closedge[i].lowcost가 closedge[i].lowcost보다 작으면 closedge[i].lowcost를 새 에지의 가중치로 업데이트합니다.
3.2 구현 중 개인이 직면한 문제
Geng 씨는 v를 U에 통합한 후 closedge[v].lowcost=0으로 설정하지만 closedge[i].lowcost=0인 에지는 새 에지를 검색할 때 쫓겨나야 합니다. 그렇지 않으면 무한 루프가 됩니다.
3.3 특정 코드
#define INFINITY 65535
struct {
int adjvex;
int lowcost;
}closedge[MAX];//辅助数组
void PrimMiniSpanTree(AdjMatrix g, int v0) {
closedge[v0].lowcost = 0;
for (int i = 0; i < g.vexnum; i++) {
if (i != v0) {
closedge[i].adjvex = v0;//初始将所有顶点的邻点设为v0
closedge[i].lowcost = g.arcs[v0][i].adj;
}
}
for (int i = 0; i < g.vexnum - 1; i++) {
//v0已经完成任务,因此循环n-1次
int min = INFINITY;//保存最小边的权值
int index = 0;//保存最小边的下标
for (int j = 0; j < g.vexnum; j++) {
if (closedge[j].lowcost != 0 && closedge[j].lowcost < min) {
min = closedge[j].lowcost;
index = j;
}
}
printf("(%c,%c) ", g.vertex[closedge[index].adjvex], g.vertex[index]);//输出最小边的信息
closedge[index].lowcost = 0;//closedge[].lowcost=0表示该顶点已经完成任务,下一次以该顶点的邻边进行搜寻。
for (int j = 0; j < g.vexnum; j++) {
if (closedge[j].lowcost != 0 && g.arcs[index][j].adj < closedge[j].lowcost) {
closedge[j].lowcost = g.arcs[index][j].adj;
closedge[j].adjvex = index;
}
}
}
}
3.4 테스트 결과
여기서 사용된 그래프와 그 가중치는 아래 그림과 같으며
여기서 A는 꼭지점으로 당연히 옳습니다.
G를 꼭지점으로 취하는
것도 분명히 맞습니다.
요약하다
아이디어를 파악하면 실현됩니다!