C 언어 기반 데이터 구조_그래프 학습 노트

목차

09 데이터 구조 다이어그램

09.1 인접행렬의 표현

09.2 인접 행렬의 구현 방법

09.3 인접 리스트의 표현 방법

09.4 인접 리스트 구현

09.5 교차 연결 리스트

09.6 인접 다중 테이블


09 데이터 구조 다이어그램

서문: 이 섹션은 주로 몇 가지 개념적인 것, 순수 토착어에 대해 설명합니다.

        큐 스택 연결 목록에 대해 이전에 이야기했습니다.이러한 구조의 경우 일부 선형 데이터 구조로 이해할 수 있습니다.이 선형 구조는 일반적으로 일대일 관계입니다.각 요소에는 고유한 해당 선행 및 후속 작업이 있습니다. , 수 선형 테이블이라고도 합니다. 트리 이진 트리의 경우 일대다 관계이므로 각 노드가 여러 노드를 가질 수 있습니다. 이 섹션의 그래프 구조는 다대다 관계입니다. 이 관계에서 두 개의 노드는 연결될 수 있습니다. 각 노드는 여러 개의 선행 노드와 후속 노드를 가질 수 있으며 이는 맵 트래픽 네트워크 다이어그램과 유사합니다. 각 도시를 점으로 상상할 수 있으며 고속도로와 철도는 모든 도시를 서로 연결합니다. 실제로 그래프의 적용은 최단 경로를 찾기 위한 회로 분석, 엔지니어링 계획 등 매우 광범위합니다.

         다음으로 그래프에 대한 몇 가지 개념이 소개됩니다. 일반적으로 그래프는 이진 그룹으로 표시될 수 있으며 그래프 G는 두 부분 VE로 나뉩니다. v는 정점을 나타내는 데 사용되고 E는 가장자리를 나타내는 데 사용됩니다. 그래프는 꼭지점과 모서리로 구성되어 있다고 할 수 있습니다. V는 꼭짓점의 집합이고 E는 가장자리의 집합입니다. V는 비어 있을 수 없고 가장자리가 없을 수 있지만 무의미할 수는 없습니다(이유는 소가 풀을 먹는 것과 같습니다. 소!배부르면 떠날거야!) 하지만 코드를 작성하는 수준에서 V는 비어있을 수 있지만 응용 프로그램에서는 그렇지 않습니다.

        일반적으로 그래프에는 무향 그래프와 방향이 방향을 나타내는 유향 그래프의 두 가지 유형이 있습니다. 유향 그래프의 경우 한 방향으로만 갈 수 있는 일방 통행로와 같으므로 무방향 그래프는 양방향 도로와 같습니다.

        (v1 v2)를 사용하여 무방향 그래프의 정점 v1 v2 사이의 관계를 나타낼 수 있습니다. <v1 v2>를 사용하여 유향 그래프 v1 v2의 관계 v1-->v2를 나타냅니다. 여기서 (v1 v2) = (v2 v1) <v1 v2> \= <v2 v1>입니다. 무방향 그래프 G1의 표현: V(G1)={V1 V2 V3 V4} E(G1)={(V1 V2),(V1 V3),( V2 V3),(...), ... } 무향 그래프의 G2 표현 V(G2)={V1 V2 V3 V4} E(G2)={<V1 V2>,<V1 V3>,<V2 V3>,<...>, ... } 요구 사항 몇 가지 특별한 경우에 주의하십시오. 대부분의 그래프는 단순 그래프이며 자가 루프가 허용되지 않습니다. 여러 그래프도 있습니다(동일한 모서리를 가진 그래프는 두 번 이상 나타날 수 없음).

완전한 그래프의 개념, 그래프의 두 지점에는 가장자리가 있습니다.

        이로부터 점의 수를 알 수 있는 수학적 지식을 이용하여 에지의 수를 구할 수 있는데, n개의 정점이 있다면 총 n(n-1)/2개의 에지가 있다. 완전 그래프 및 방향성 완전 그래프 변의 수는 n(n-1)       

        또한 네트워크의 개념을 도입하여 도시와의 거리에 따라 소비되는 시간과 돈과 유사하게 그래프 가중치 의 점 사이에 유사한 개념이 있습니다 . 가중치가 있는 그래프를 네트워크라고 합니다.

         두 가지 중요한 개념: 인접성연관성 . 인접성은 꼭짓점 사이의 관계로, 두 꼭지점이 공통 모서리를 공유하는 경우 이를 상호 인접성이라고 합니다.v1이 V2에 연결되거나 v2가 v1에 연결된다고 할 수 있습니다. 연결은 모서리와 정점 사이의 관계를 나타냅니다. 정점에 인접한 가장자리의 경우 가장자리 연결을 v1 및 v2라고 부를 수 있습니다.

        정도 : 꼭지점의 정도는 꼭지점과 관련된 모서리의 수를 의미합니다.여기에 악수 정리가 있습니다.그래프의 각도의 합은 모서리 수의 두 배입니다. 그 이유는 간단합니다.도의 합을 계산할 때 각 모서리는 두 번 계산됩니다.

        유방향 그래프에서 각도는 인도아웃도로 더 나뉩니다 . In-degree는 해당 지점을 끝점으로 하고 out-degree는 해당 지점을 시작점으로 합니다. 또한 모든 꼭짓점의 out-degree 합은 in-degree 합과 같으며, 이것도 out-degree가 있으면 in-degree가 있어야 하므로 서로 같다는 것을 이해하면 매우 좋습니다.

        경로: 연속된 모서리로 연결된 정점의 시퀀스(즉, 하나의 모서리가 다른 모서리에 완전히 연결됨) 경로의 길이는 모서리의 수를 나타냅니다.

        여기에 몇 가지 개념이 더 있습니다! 루프백 경로첫 번째 꼭지점과 마지막 꼭짓점이 같다는 것입니다. 단순 회로란 머리와 꼬리 중간을 제외한 각 노드의 반복이 없다는 것을 의미하며, 반복이 있으면 비단순 회로입니다. 단순 경로: vi에서 vj까지의 각 정점이 반복되지 않는 하위 그래프 : 그래프에서 여러 개의 정점과 여러 개의 간선을 빼낸 그래프. Generate a subgraph : 모든 정점과 여러 모서리를 제거합니다. 연결 그래프 : 반드시 인접하지 않아도 되는 꼭지점 vi와 j 사이에 경로가 존재하며, 그래프에서 임의의 두 점이 연결되면 연결 그래프라고 부를 수 있습니다. 연결 성분 : 무방향 그래프의 가장 큰 연결 부분 그래프(점 추가는 연결되지 않음)를 연결 성분이라고 합니다. 연결된 그래프의 경우 가장 큰 연결 구성 요소는 자체입니다. 유향 그래프의 경우 강하게 연결된 그래프강하게 연결된 성분 으로 나눌 수 있으며 vi에서 vj로 가는 경로가 있고 vj에서 vi로 가는 경로도 있습니다. 가장 큰 강하게 연결된 하위 그래프는 점을 추가하는 것이므로 강하게 연결된 그래프가 아닙니다.

09.1  인접행렬의 표현

이제 방향 그래프의 노드, 노드 차수, 아웃 차수 및 인 차수와 같은 정보를 저장하는 기능이 필요한 데이터 표현 방법을 설계하십시오...

무방향 그래프의 표현

 무향 그래프 인접 행렬의 특성: 대각선을 따라 대칭, i번째 행 또는 i번째 열의 0이 아닌 요소의 수는 i번째 꼭지점의 차수 와 같습니다 .

유방향 그래프 표현

 방향 그래프 인접 행렬의 특징: 반드시 대칭일 필요는 없음, i번째 행의 0이 아닌 요소의 수는 i번째 꼭지점의 out-degree 와 같음, i번째 행의 0이 아닌 요소의 수 -번째 열은 i번째 꼭지점의 차수 와 같습니다 .

그물의 표현

특징은 방향 그래프와 동일하며 노드 요소의 In-degree 및 Out-degree를 쉽게 얻을 수 있을 뿐만 아니라 경로 가중치를 쉽게 볼 수 있습니다.

09.2 인접 행렬의 구현 방법

당연히 행렬을 저장하기 위해서는 노드 정보를 저장할 2차원 배열과 1차원 배열이 필요하며, 배열의 순회 연산을 돕기 위해서는 꼭지점 수를 저장하는 2개의 요소와 모서리 수.

무향 그래프 코드 생성

#include <stdio.h>
#include <stdlib.h>

#define MAX 100

struct AMG_Graph
{
	int vex_num, edge_num;

	char Vex[MAX];
	int Edge[MAX][MAX];
};

struct AMG_Graph *Create_AMG_Graph(void);
void Show_AMG_Graph(struct AMG_Graph *graph);
int search_vex(struct AMG_Graph *graph, char c);

int main(void)
{
	struct AMG_Graph *ud_graph;

	ud_graph = Create_AMG_Graph();
	Show_AMG_Graph(ud_graph);

	return 0;
}

struct AMG_Graph *Create_AMG_Graph(void)
{
	int i, j;
	char u, v;

	struct AMG_Graph *graph;

	graph = (struct AMG_Graph *)malloc(sizeof(struct AMG_Graph));

	printf("Please enter the number of vex: ");
	scanf("%d", &graph->vex_num);
	printf("Please enter the number of edge: ");
	scanf("%d", &graph->edge_num);

	while(getchar() != '\n');

	printf("Please enter vertex:\n");
	for(i = 0; i < graph->vex_num; i++)
	{
		graph->Vex[i] = getchar();
		while(getchar() != '\n');
	}

	for(i = 0; i < graph->vex_num; i++)
	{
		for(j = 0; j < graph->vex_num; j++)
			graph->Edge[i][j] = 0;
	}

	while(graph->edge_num--)
	{
		printf("Please enter the vex that connect each other by edge:\n");
		u = getchar();
		while(getchar() != '\n');
		v = getchar();
		while(getchar() != '\n');

		i = search_vex(graph, u);
		j = search_vex(graph, v);

		if(i != -1 && j != -1)
			graph->Edge[i][j] = graph->Edge[j][i] = 1;
		else
		{
			printf("You have entered wrong vex, please enter again.\n");
			graph->edge_num++;
		}

	}

	return graph;
}

void Show_AMG_Graph(struct AMG_Graph *graph)
{
	int i, j;

	printf("Show the vex: \n");
	for(i = 0; i < graph->vex_num; i++)
		printf("%c ", graph->Vex[i]);
	printf("\n");

	printf("Show the adjacency matrices:\n");
	for(i = 0; i< graph->vex_num; i++)
	{
		for(j = 0; j < graph->vex_num; j++)
			printf("%d\t", graph->Edge[i][j]);
		printf("\n");
	}
}

int search_vex(struct AMG_Graph *graph, char c)
{
	int i;

	for(i = 0; i < graph->vex_num; i++)
	{
		if(c == graph->Vex[i])
			return i;
	}

	return -1;
}

유방향 그래프 코드 생성은
        무방향 그래프 코드를 기준으로 그래프->Edge[i][j] = 그래프->Edge[j][i] = 1 로 삭제하고 수정하면 이 부분이면 충분하다.

#include <stdio.h>
#include <stdlib.h>

#define MAX 100

struct AMG_Graph
{
	int vex_num, edge_num;

	char Vex[MAX];
	int Edge[MAX][MAX];
};

struct AMG_Graph *Create_AMG_Graph(void);
void Show_AMG_Graph(struct AMG_Graph *graph);
int search_vex(struct AMG_Graph *graph, char c);

int main(void)
{
	struct AMG_Graph *ud_graph;

	ud_graph = Create_AMG_Graph();
	Show_AMG_Graph(ud_graph);

	return 0;
}

struct AMG_Graph *Create_AMG_Graph(void)
{
	int i, j;
	char u, v;

	struct AMG_Graph *graph;

	graph = (struct AMG_Graph *)malloc(sizeof(struct AMG_Graph));

	printf("Please enter the number of vex: ");
	scanf("%d", &graph->vex_num);
	printf("Please enter the number of edge: ");
	scanf("%d", &graph->edge_num);

	while(getchar() != '\n');

	printf("Please enter vertex:\n");
	for(i = 0; i < graph->vex_num; i++)
	{
		graph->Vex[i] = getchar();
		while(getchar() != '\n');
	}

	for(i = 0; i < graph->vex_num; i++)
	{
		for(j = 0; j < graph->vex_num; j++)
			graph->Edge[i][j] = 0;
	}

	while(graph->edge_num--)
	{
		printf("Please enter the vex that connect each other by edge:\n");
		u = getchar();
		while(getchar() != '\n');
		v = getchar();
		while(getchar() != '\n');

		i = search_vex(graph, u);
		j = search_vex(graph, v);

		if(i != -1 && j != -1)
			graph->Edge[i][j] = 1;
		else
		{
			printf("You have entered wrong vex, please enter again.\n");
			graph->edge_num++;
		}

	}

	return graph;
}

void Show_AMG_Graph(struct AMG_Graph *graph)
{
	int i, j;

	printf("Show the vex: \n");
	for(i = 0; i < graph->vex_num; i++)
		printf("%c ", graph->Vex[i]);
	printf("\n");

	printf("Show the adjacency matrices:\n");
	for(i = 0; i< graph->vex_num; i++)
	{
		for(j = 0; j < graph->vex_num; j++)
			printf("%d\t", graph->Edge[i][j]);
		printf("\n");
	}
}

int search_vex(struct AMG_Graph *graph, char c)
{
	int i;

	for(i = 0; i < graph->vex_num; i++)
	{
		if(c == graph->Vex[i])
			return i;
	}

	return -1;
}

09.3  인접 리스트의 표현 방법

인접행렬의 2차원 그래프의 행과 열의 관계를 이용하여 그래프의 차수, 내차수, 외차수를 쉽게 구할 수 있으며, 이 데이터 구조 관계는 순차적으로 저장된다. 행렬, 2차원 배열을 형성하기 위해 많은 공간을 낭비하고 모든 배열에 값이 할당되지는 않는다는 것을 알게 될 것입니다.

따라서 연결된 저장소와 같은 그래프를 나타내는 다른 방법이 있습니다. 답변: 예... 인접 목록입니다. 인접 리스트에 대한 연구는 표현 그래프의 차수, 차수, 차수를 저장하는 방법에 초점을 맞춰야 하며 행렬의 표현 방법을 비교할 수 있습니다.

무방향 그래프의 인접 리스트

 특징: n노드와 e에지의 경우 정점 테이블에는 n노드가 있고 인접 접촉 테이블에는 2e노드가 있습니다.

유방향 그래프의 인접 목록

 특징: n노드와 e에지의 경우 정점 테이블에는 n노드가 있고 인접 접촉 테이블에는 e노드가 있습니다. 꼭짓점의 out-degree는 꼭짓점 뒤에 있는 single-linked list의 노드 수이며, in-degree는 인접 포인트 테이블을 통과한 후 계산해야 합니다. (아웃도보다 인도 계산에 더 주의를 기울이면 화살표를 가리켜 부정하고 역 인접 목록을 사용할 수 있습니다 .)

09.4 인접 리스트 구현

유방향 그래프의 인접 목록

#include <stdio.h>
#include <stdlib.h>

#define MAX 100

struct AdjNode
{
	int index;
	struct AdjNode *next;
};

struct VexNode
{
	char node;
	struct AdjNode *first;
};

struct ALG_Graph
{
	int vex_num, edge_num;
	struct VexNode Vex[MAX];
};

struct ALG_Graph *Create_ALG_Graph(void);
int search_vex(struct ALG_Graph *graph, char c);
void create_adj_node_list(struct ALG_Graph *graph, int i, int j);
void Show_ALG_Graph(struct ALG_Graph *graph);


int main(void)
{
	struct ALG_Graph *d_graph;
	d_graph = Create_ALG_Graph();
	Show_ALG_Graph(d_graph);
	return 0;
}

struct ALG_Graph *Create_ALG_Graph(void)
{
	int i, j;
	char u, v;

	struct ALG_Graph *graph;

	graph = (struct ALG_Graph *)malloc(sizeof(struct ALG_Graph));

	printf("Please enter the number of vex: ");
	scanf("%d", &graph->vex_num);
	printf("Please enter the number of edge: ");
	scanf("%d", &graph->edge_num);
	while(getchar() != '\n');

	printf("Please enter vertex:\n");
	for(i = 0; i < graph->vex_num; i++)
	{
		graph->Vex[i].node = getchar();
		while(getchar() != '\n');
	}

	for(i = 0; i < graph->vex_num; i++)
	{
		graph->Vex[i].first = NULL;
	}

	while(graph->edge_num--)
	{
		printf("Please enter the vex that connect each other by edge:\n");
		u = getchar();
		while(getchar() != '\n');
		v = getchar();
		while(getchar() != '\n');

		i = search_vex(graph, u);
		j = search_vex(graph, v);

		if(i != -1 && j != -1)
			create_adj_node_list(graph, i, j);
		else
		{
			printf("You have entered wrong vex, please enter again.\n");
			graph->edge_num++;
		}
	}
	return graph;
}

int search_vex(struct ALG_Graph *graph, char c)
{
	int i;

	for(i = 0; i < graph->vex_num; i++)
	{
		if(c == graph->Vex[i].node)
			return i;
	}

	return -1;
}

void create_adj_node_list(struct ALG_Graph *graph, int i, int j)
{
	struct AdjNode *s = (struct AdjNode *)malloc(sizeof(struct AdjNode));
	s->index = j;
	s->next = graph->Vex[i].first;
	graph->Vex[i].first = s;
}

void Show_ALG_Graph(struct ALG_Graph *graph)
{
	int i;
	struct AdjNode *t;

	printf("Show the ALG Graph:\n");

	for(i = 0; i < graph->vex_num; i++)
	{
		printf("%c: ", graph->Vex[i].node);
		t = graph->Vex[i].first;
		while(t != NULL)
		{
			printf("%d ", t->index);
			t = t->next;
		}
		printf("\n");
	}
}

무방향 그래프의 인접 리스트

#include <stdio.h>
#include <stdlib.h>

#define MAX 100

struct AdjNode
{
	int index;
	struct AdjNode *next;
};

struct VexNode
{
	char node;
	struct AdjNode *first;
};

struct ALG_Graph
{
	int vex_num, edge_num;
	struct VexNode Vex[MAX];
};

struct ALG_Graph *Create_ALG_Graph(void);
int search_vex(struct ALG_Graph *graph, char c);
void create_adj_node_list(struct ALG_Graph *graph, int i, int j);
void Show_ALG_Graph(struct ALG_Graph *graph);


int main(void)
{
	struct ALG_Graph *md_graph;
	md_graph = Create_ALG_Graph();
	Show_ALG_Graph(md_graph);

	return 0;
}

struct ALG_Graph *Create_ALG_Graph(void)
{
	int i, j;
	char u, v;

	struct ALG_Graph *graph;

	graph = (struct ALG_Graph *)malloc(sizeof(struct ALG_Graph));

	printf("Please enter the number of vex: ");
	scanf("%d", &graph->vex_num);
	printf("Please enter the number of edge: ");
	scanf("%d", &graph->edge_num);
	while(getchar() != '\n');

	printf("Please enter vertex:\n");
	for(i = 0; i < graph->vex_num; i++)
	{
		graph->Vex[i].node = getchar();
		while(getchar() != '\n');
	}

	for(i = 0; i < graph->vex_num; i++)
	{
		graph->Vex[i].first = NULL;
	}

	while(graph->edge_num--)
	{
		printf("Please enter the vex that connect each other by edge:\n");
		u = getchar();
		while(getchar() != '\n');
		v = getchar();
		while(getchar() != '\n');

		i = search_vex(graph, u);
		j = search_vex(graph, v);

		if(i != -1 && j != -1){
			create_adj_node_list(graph, i, j);
            create_adj_node_list(graph, j, i);
        }
		else
		{
			printf("You have entered wrong vex, please enter again.\n");
			graph->edge_num++;
		}
	}
	return graph;
}

int search_vex(struct ALG_Graph *graph, char c)
{
	int i;

	for(i = 0; i < graph->vex_num; i++)
	{
		if(c == graph->Vex[i].node)
			return i;
	}

	return -1;
}

void create_adj_node_list(struct ALG_Graph *graph, int i, int j)
{
	struct AdjNode *s = (struct AdjNode *)malloc(sizeof(struct AdjNode));
	s->index = j;
	s->next = graph->Vex[i].first;
	graph->Vex[i].first = s;
}

void Show_ALG_Graph(struct ALG_Graph *graph)
{
	int i;
	struct AdjNode *t;

	printf("Show the ALG Graph:\n");

	for(i = 0; i < graph->vex_num; i++)
	{
		printf("%c: ", graph->Vex[i].node);
		t = graph->Vex[i].first;
		while(t != NULL)
		{
			printf("%d ", t->index);
			t = t->next;
		}
		printf("\n");
	}
}

09.5 교차 연결 리스트

일반적인 인접 리스트의 경우 out-degree에 주목하면 유향 그래프의 인접 리스트를 사용할 수 있고 반대로 in-degree에 주의하면 유향 그래프의 역 인접 리스트를 사용할 수 있습니다. 그렇다면 in-degree와 out-degree를 모두 쉽게 볼 수 있는 더 나은 솔루션이 있습니까?linked list...- cross linked list를 기반으로 약간의 공간을 추가해야 합니다 .

교차 연결 목록은 노드 테이블 + 에지 노드 테이블로 구성됩니다.(여기서 부르는 것이 가장 중요한 개념은 아닙니다.) 노드
테이블은 정점, 들어오는 아크 + 나가는 아크(들어오는 아크와 나가는 아크는 포인터입니다)와 경계
포인트 테이블은 꼬리 + 머리 + 같은 머리 + 꼬리로 구성됩니다.

09.6 인접 다중 테이블

무방향 그래프의 인접 목록과 비교하여 인접 다중 테이블은 에지의 일부 연산에 더 많은 주의를 기울입니다.

추천

출처blog.csdn.net/shelter1234567/article/details/130387573