-> 블로그 이전

[Data Structure] 그래프 표현 방법 1) 인접 행렬

2021. 12. 22. 15:34Major`/자료구조

그래프의 표현방법

  • 인접 행렬(Adjacency Matrix) : 2차원 배열을 사용
  • 인접 리스트(Adjacency List) : 연결 리스트를 사용

인접 행렬

- 정점의 수 n개에 대해 n×n의 2차원 배열로 구성

- 간선 (i, j)가 그래프에 존재하면 m[i][j] = 1

- 간선 (i, j)가 그래프에 없으면 m[i][j] = 0

- n개의 정점이 존재하면 n²개의 메모리가 필요

  • → 메모리 낭비가 크다

- 간선이 매우 많은 밀집 그래프에는 적합하다

- 간선이 적은 희소 그래프의 경우에는 메모리 낭비가 크므로 적합하지 않다

  • 무방향 그래프 = 행렬이 대칭으로 구성

그래프 인접행렬 구현

#define MAX_VERTEX 50

typedef struct graph {
	int n; // 정점의 개수 count(vertex)
	int vertex[MAX_VERTEX]; // 정점 저장 배열
	int matrix[MAX_VERTEX][MAX_VERTEX]; // 인접 행렬 (2차원 배열)
}graph;

 

 

1. Vertex 삽입 연산

  • 정점의 개수가 MAX_VERTEX에 도달하면 더 이상 INSERT X
void insert_vertex(graph* g, int v) {
	if (is_full(g)) {
		fprintf(stderr, "그래프 정점의 개수가 MAX에 도달하였습니다\n\n");
		return;
	}
	else if (bool_vertex(g, v) == 0) {
		fprintf(stderr, "해당 정점은 이미 그래프에 존재합니다.\n\n");
		return;
	}
	g->vertex[g->n++] = v;
}

 

 

2. Edge 삽입 연산

  • 무방향 그래프에서는 대칭적으로 start-end / end-start에 1을 삽입
  • 방향 그래프에서는 해당 방향만 1 삽입
int bool_vertex(graph* g, int v) {
	// 그래프에 정점 v가 존재하는지 판별
	int flag = 1;
	for (int i = 0; i < MAX_VERTEX; i++) {
		if (g->vertex[i] == v)
			flag = 0; // 존재 O
	}
	if (flag == 0) return 0; // 존재 O
	else return 1; // 존재 X
}

void insert_edge(graph* g, int start, int end) { // start - end를 연결하는 edge 생성
	if (bool_vertex(g, start) == 1 || bool_vertex(g, end) == 1) {
		fprintf(stderr, "그래프에 해당 정점은 없습니다\n\n");
		return;
	}
	g->matrix[start][end] = 1;
	g->matrix[end][start] = 1;
	// 무방향 그래프이기 때문에 대칭적으로 1 삽입
}

 

 

3. Edge 삭제 연산

void delete_edge(graph* g, int start, int end) { // start - end 연결하는 edge 삭제
	if (bool_vertex(g, start) == 1 || bool_vertex(g, end) == 1) {
		fprintf(stderr, "그래프에 해당 정점은 없습니다\n\n");
		return;
	}
	g->matrix[start][end] = 0;
	g->matrix[end][start] = 0;
}

 

 

4. Full Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 인접 행렬 (무방향 그래프)

#define MAX_VERTEX 50

typedef struct graph {
	int n; // 정점의 개수 count(vertex)
	int vertex[MAX_VERTEX]; // 정점 저장 배열
	int matrix[MAX_VERTEX][MAX_VERTEX]; // 인접 행렬 (2차원 배열)
}graph;

graph* create() { // 그래프 동적 할당
	return (graph*)malloc(sizeof(graph));
}

void init_graph(graph* g) { // 그래프 초기화
	int r, c; // row, col
	g->n = 0; // 정점의 개수 0으로 초기화
	for (r = 0; r < MAX_VERTEX; r++) {
		for (c = 0; c < MAX_VERTEX; c++) {
			g->matrix[r][c] = 0; // 2차원 배열 전부 0으로 초기화
		}
	}
}

int bool_vertex(graph* g, int v) {
	// 그래프에 정점 v가 존재하는지 판별
	int flag = 1;
	for (int i = 0; i < MAX_VERTEX; i++) {
		if (g->vertex[i] == v)
			flag = 0; // 존재 O
	}
	if (flag == 0) return 0; // 존재 O
	else return 1; // 존재 X
}

int is_full(graph* g) {
	return g->n == MAX_VERTEX;
}

void insert_vertex(graph* g, int v) {
	if (is_full(g)) {
		fprintf(stderr, "그래프 정점의 개수가 MAX에 도달하였습니다\n\n");
		return;
	}
	else if (bool_vertex(g, v) == 0) {
		fprintf(stderr, "해당 정점은 이미 그래프에 존재합니다.\n\n");
		return;
	}
	g->vertex[g->n++] = v;
}

void insert_edge(graph* g, int start, int end) { // start - end를 연결하는 edge 생성
	if (bool_vertex(g, start) == 1 || bool_vertex(g, end) == 1) {
		fprintf(stderr, "그래프에 해당 정점은 없습니다\n\n");
		return;
	}
	g->matrix[start][end] = 1;
	g->matrix[end][start] = 1;
	// 무방향 그래프이기 때문에 대칭적으로 1 삽입
}

void delete_edge(graph* g, int start, int end) { // start - end 연결하는 edge 삭제
	if (bool_vertex(g, start) == 1 || bool_vertex(g, end) == 1) {
		fprintf(stderr, "그래프에 해당 정점은 없습니다\n\n");
		return;
	}
	g->matrix[start][end] = 0;
	g->matrix[end][start] = 0;
}

void print_matrix(graph* g) {
	for (int i = 0; i < g->n; i++) {
		printf("%d |", g->vertex[i]);
		for (int j = 0; j < g->n; j++) {
			printf("%2d", g->matrix[i][j]);
		}
		printf("\n");
	}
}

int main(void) {
	graph* g1, *g2;
	g1 = create();
	g2 = create();
	init_graph(g1);
	init_graph(g2);

	printf("V : {0, 1, 2, 3}\n");
	printf("E : {(0, 1), (0, 2), (0, 3), (1, 2), (2, 3)\n\n");
	for (int i = 0; i < 4; i++)
		insert_vertex(g1, i);
	insert_edge(g1, 0, 1);
	insert_edge(g1, 0, 2);
	insert_edge(g1, 0, 3);
	insert_edge(g1, 1, 2);
	insert_edge(g1, 2, 3);

	// print
	printf("   ");
	for (int i = 0; i < g1->n; i++)
		printf("%2d", i);
	printf("\n   ");
	for (int i = 0; i < g1->n; i++)
		printf("--");
	printf("\n");
	print_matrix(g1);
	// print

	printf("----------------------------\n");
	printf("V : {0, 1, 2, 3, 4}\n");
	printf("E : {(0, 1), (0, 2), (0, 3), (1, 2), (1, 4), (2, 3), (3, 4)\n\n");
	for (int i = 0; i < 5; i++)
		insert_vertex(g2, i);
	insert_edge(g2, 0, 1);
	insert_edge(g2, 0, 2);
	insert_edge(g2, 0, 3);
	insert_edge(g2, 1, 2);
	insert_edge(g2, 1, 4);
	insert_edge(g2, 2, 3);
	insert_edge(g2, 3, 4);

	// print
	printf("   ");
	for (int i = 0; i < g2->n; i++)
		printf("%2d", i);
	printf("\n   ");
	for (int i = 0; i < g2->n; i++)
		printf("--");
	printf("\n");
	print_matrix(g2);
	// print

	return 0;
}