최소 스패닝 트리-Plim의 알고리즘(덧셈 방식) 및 구현[C/C++]


머리말

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를 꼭지점으로 취하는
여기에 이미지 설명 삽입
것도 분명히 맞습니다.


요약하다

아이디어를 파악하면 실현됩니다!

Supongo que te gusta

Origin blog.csdn.net/qq_45400167/article/details/126645824
Recomendado
Clasificación