무향 그래프에서 정점 v0으로부터의 거리가 최단 경로 길이 K인 모든 정점을 찾습니다. [C/C++]


머리말

Geng Guohua의 데이터 구조 제2판을 보고 있습니다.문제 7.6 무향 그래프의 정점 v0에서 최단 경로 길이 K를 갖는 모든 정점을 찾으십시오.Geng Guohua의 아이디어에 따라 재현할 수 없습니다. 약간의 문제가 있다고 느끼며, 아마도 내가 조금 더 나아졌기 때문에, 그것을 달성하기 위해 생각의 방식을 바꿨습니다.


1. 겅 선생님의 생각

정점 v0부터 너비 우선 탐색을 시작하여 한 단계, 두 단계… 의 꼭지점은 원하는 것입니다.

2. 내 생각

1. 분석 아이디어

여기서 Geng 씨는 두 개의 대기열, 하나의 스토리지 노드 및 하나의 스토리지 레이어를 사용하는 것 같습니다. 아이디어가 매우 좋습니다. 여기서 계속하겠습니다. STL을 배웠다면 unordered_map, unordered_map<int,int>, 키 값 저장 계층 번호, val은 정점 번호를 저장한 다음 키 값에 따라 설정된 길이 K와 비교하여 K와 동일한 해시 순서 체인을 출력합니다. 지도 컨테이너의 경우 여기서는 아이디어에 대해서만 이야기하고 구현도 매우 쉽습니다.
Geng 씨의 생각에 따르면 여전히 계속됩니다.
여기서 우리는 무향 그래프의 non-recursive breadth traversal을 언급해야 하는데, 여기서 각 레이어의 꼭지점은 차례대로 queue에 입력되므로 K-step reachability는 v0을 k번째 레이어 노드를 출력하는 것입니다. 꼭지점. 본질적으로 첫 번째 dequeue의 레이어 번호가 K와 같으면 이때 대기열의 모든 요소는 k번째 레이어에서 온 것입니다.
이것은 문제를 훨씬 더 간단하게 만듭니다.
먼저 무방향 그래프의 비재귀 순회를 위한 너비 우선 알고리즘을 작성합니다.
여기서 인접 목록은 무방향 그래프를 나타내는 데 사용됩니다.

2. 무향 그래프의 비재귀 순회를 위한 너비 우선 알고리즘

코드는 다음과 같습니다(예제).

void NoReBroadFirstSearch(AdjList g, int v) {
    
    
	printf("%c ", g.vertexlist[v].data);
	visited[v] = 1;
	queue<int>Q;
	Q.push(v);
	while (!Q.empty()) {
    
    
		int front = Q.front();
		ArcNode* p = g.vertexlist[front].firstarc;
		while (p != NULL) {
    
    
			if (!visited[p->adjvex]) {
    
    
				printf("%c ", g.vertexlist[p->adjvex].data);
				visited[p->adjvex] = 1;
				Q.push(p->adjvex);
			}
			p = p->nextarc;
		}
		if (p == NULL) {
    
    
			Q.pop();
		}
	}
}
void NoReTraverseGrap(AdjList g) {
    
    
	for (int vi = 0; vi < g.vexnum; vi++) {
    
    
		visited[vi] = 0;
	}
	for (int vi = 0; vi < g.vexnum; vi++) {
    
    
		if (!visited[vi]) {
    
    
			NoReBroadFirstSearch(g, vi);
		}
	}
}

3. 이전 단계의 알고리즘 개선

이중 대기열, 하나의 스토리지 노드 및 하나의 스토리지 레이어 번호를 사용하여 Geng 씨의 생각을 계속합니다.
v0을 방문한 것으로 설정하고 초기 레이어 번호는 0입니다. 그리고 큐에 넣습니다.

queue<int>QNode;
queue<int>QLevel;
visited[v0] = 1;
int level = 0;
QNode.push(v0);
QLevel.push(level);

대기열이 비어 있지 않고 레이어 수가 설정된 단계 수보다 적은 한, 대기열에서 빼기 전에 첫 번째 대기열에서 빼는 레이어 번호가 단계 수 K인지 여부를 판단합니다.
스텝의 개수 K라면 큐에 있는 모든 원소는 스텝의 개수가 K인 레이어의 원소이고 큐는 비어있고 출력된다.
스텝의 개수 K가 아니면 먼저 두 개의 큐 중 하나를 차례로 디큐하고, 디큐된 정점에 따라 폭 검색을 수행하고, 액세스가 없으면 큐에 들어갑니다.

4. 특정 코드

여기서 단계 수 K는 len이고 초기 정점은 v0입니다.

void FindNodeSetLenPath(AdjList g, int v0, int len) {
    
    
	queue<int>QNode;//顶点队列
	queue<int>QLevel;//层号队列
	for (int i = 0; i < g.vexnum; i++) {
    
    
		visited[i] = 0;//初始化访问标志数组
	}
	visited[v0] = 1;
	int level = 0;//初始层号
	QNode.push(v0);
	QLevel.push(level);
	while (!QNode.empty() && level <= len) {
    
    
		int curnode = QNode.front();
		level = QLevel.front();
		if (level == len) {
    
    
			while (!QNode.empty()) {
    
    
				int front = QNode.front();
				printf("%c ", g.vertexlist[front].data);
				QNode.pop();
			}
			return;
		}
		QNode.pop();
		QLevel.pop();
		ArcNode* p = g.vertexlist[curnode].firstarc;
		for (p; p != NULL; p = p->nextarc) {
    
    
			if (!visited[p->adjvex]) {
    
    
				visited[p->adjvex] = 1;
				QNode.push(p->adjvex);
				QLevel.push(level + 1);
			}
		}
	}
}

5. 테스트 결과

여기에서는 여전히 더 복잡한 다이어그램이 사용됩니다.

여기에 이미지 설명 삽입
먼저 G 꼭지점 단계가 2인 노드를 찾자.
여기에 이미지 설명 삽입G 꼭지점의 2단계 노드를 AICE로 하자.
어떤 사람들은 여기서 질문할 수 있다. 당신의 넓이 순회는 틀렸다. 당신이 말한 것이 이치에 맞고 틀렸지만 나는 그렇지 않다. 바꾸고 싶다, 흐흐. 이 너비 우선 순위는 두 가지 요인에 의해 영향을 받는데, 첫째는 인접 목록을 작성할 때 머리 삽입 방법을 사용하는지 꼬리 삽입 방법을 사용하는지 여부이고, 두 번째는 인접 목록을 작성할 때 노드의 입력 순서입니다.
하지만 인접행렬이라면 문제가 그렇게 많지 않아서 짜증나죠!
다시 반시계 방향으로 노드를 입력하겠습니다.
여기에 이미지 설명 삽입
여기서 폭 순회는 노드를 시계 반대 방향으로 출력하는 것이므로 완벽합니다.
그런 다음 정점이 H이고 단계 수가 3인 노드를 테스트하고
여기에 이미지 설명 삽입
노드 A만 라인에 있는
노드를 테스트한 다음 I 노드의 단계 수가 2인 노드를 테스트합니다.
여기에 이미지 설명 삽입

AGHE
퀴즈를 맞혀보세요!


요약하다

여기서 단계 수 len은 v0 정점을 갖는 lenth 레이어로 이해될 수 있으므로 문제가 쉽게 해결됩니다.

Supongo que te gusta

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