우선순위 큐
정의 :
큐(Queue)는 먼저 들어오는 데이터가 먼저 나가는 FIFO(First In First Out) 형식의 자료구조이다.
우선순위 큐(Priority Queue)는 먼저 들어오는 데이터가 아니라, 우선순위가 높은 데이터가 먼저 나가는 형태의 자료구조이다.
구현 방법 :
배열, 연결 리스트, 히프를 사용해서 구현 가능
히프
정의 :
무엇인가를 차곡차곡 쌓아올린 더미라는 뜻을 의미하는 자료구조
1. 항상 부모 노드 > 자식 노드
2. 히프는 완전 이진 트리,
완전 이진트리는 높이가 h 일 때 레벨 h-1까지는 Full BT이고, 레벨 h에서는 왼쪽부터 노드가 순서대로 채워진 이진트리이다.
3. 2종류 : 최대 히프(부모 노드 > 자식 노드), 최소 히프(부모 노드<자식 노드)
이진 탐색 트리
정의 : 이진 트리 기반의 탐색을 위한 자료구조
- 모든 원소의 키는 유일한 키를 가짐
- 왼쪽 서브 트리의 키들은 루트 키 보다 작다
- 오른쪽 서브 트리의 키들은 루트 키 보다 크다
- 왼쪽과 오른쪽 서브 트리도 이진 탐색 트리이다 (위에 조건들이 서브 트리들에게도 성립)
탐색 연산 2가지 : 재귀 탐색 연산, 반복 탐색 연산
삽입 연산, 삭제 연산
시간 복잡도 : O(log2h)
최악의 경우 선형 탐색 트리와 다를 바가 없음 = O(N)
트리의 높이를 log2n으로 한정시키는 균형기법이 필요
==> AVL 트리가 개발됨
AVL 트리
정의 : 각 노드에서 왼쪽 서브 트리의 높이와 오른쪽 서브 트리의 높이 차이가 1 이하인 이진 탐색 트리
BST에서 추가된 점
: 균형을 맞추기 위해서 함수들이 추가됨
#include<stdio.h>
#include<stdlib.h>
#define MAX(a, b) (a)
// AVL 트리 노드 정의
typedef struct AVLNode
{
int key;
struct AVLNode* left;
struct AVLNode* right;
} AVLNode;
// 트리의 높이를 반환
int get_height(AVLNode* node)
{
int height = 0;
if (node != NULL)
height = 1 + max(get_height(node->left),
get_height(node->right));
return height;
}
// 노드의 균형인수를 반환
int get_balance(AVLNode* node)
{
if (node == NULL) return 0;
return get_height(node->left)
- get_height(node->right);
}
// 노드를 동적으로 생성하는 함수
AVLNode* create_node(int key)
{
AVLNode* node = (AVLNode*)malloc(sizeof(AVLNode));
node->key = key;
node->left = NULL;
node->right = NULL;
return(node);
}
// 오른쪽으로 회전시키는 함수
AVLNode* rotate_right(AVLNode* parent)
{
AVLNode* child = parent->left;
parent->left = child->right;
child->right = parent;
// 새로운 루트를 반환
return child;
}
// 왼쪽으로 회전시키는 함수
AVLNode* rotate_left(AVLNode* parent)
{
AVLNode* child = parent->right;
parent->right = child->left;
child->left = parent;
// 새로운 루트 반환
return child;
}
// AVL 트리에 새로운 노드 추가 함수
// 새로운 루트를 반환한다.
AVLNode* insert(AVLNode* node, int key)
{
// 이진 탐색 트리의 노드 추가 수행
if (node == NULL)
return(create_node(key));
if (key < node->key)
node->left = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);
else // 동일한 키는 허용되지 않음
return node;
// 노드들의 균형인수 재계산
int balance = get_balance(node);
// LL 타입 처리
if (balance > 1 && key < node->left->key)
return rotate_right(node);
// RR 타입 처리
if (balance < -1 && key > node->right->key)
return rotate_left(node);
// LR 타입 처리
if (balance > 1 && key > node->left->key)
{
node->left = rotate_right(node->left);
return rotate_right(node);
}
// RL 타입 처리
if (balance < -1 && key < node->right->key)
{
node->right = rotate_right(node->right);
return rotate_left(node);
}
return node;
}
// 전위 순회 함수
void preorder(AVLNode* root)
{
if (root != NULL)
{
printf("[%d] ", root->key);
preorder(root->left);
preorder(root->right);
}
}
int main(void)
{
AVLNode* root = NULL;
// 예제 트리 구축
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 40);
root = insert(root, 50);
root = insert(root, 29);
printf("전위 순회 결과 \n");
preorder(root);
return 0;
}
2-3 트리
정의: 차수가 2 또는 3인 노드를 가지는 트리
하나의 노드가 2개 or 3개의 자식 노드를 가짐
// 2-3 트리 search 함수
Tree23Node* tree23_searchi(Tree23Node* root, int key)
{
if (root == NULL)
return FALSE;
else if (key == root->data)
return TRUE;
else if (root->type == TWO_NODE) {
// 2-노드
if (key < root->key)
return tree23_search(root->left, key);
else
return tree23_search(root->right, key);
}
else {
// 3-노드
if(key < root->key1)
return tree23_search(root->left, key);
else if (key > root->key2)
return tree23_search(root->right, key);
else
return tree23_search(root->middle, key);
}
}
- 단말 노드를 분리하는 경우
- 비단말 노드를 분리하는 경우
- 루트 노드를 분리하는 경우
2-3-4 트리
2-3-4 트리는 하나의 노드가 4개의 자식까지 가질 수 있도록 2-3트리를 확장한 것
레드블랙 트리
Red-black tree(이하 “RB Tree”)는 일종의 자기 균형 이진 탐색 트리(Self-Balancing BST)입니다.
다이제스트라 최단 경로 알고리즘
: 네트워크에서 하나의 시작 정점으로부터 모든 다른 정점까지의 최단 경로를 찾는 알고리즘
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define TRUE 1
#define FALSE 0
#define MAX_VERTICES 100
#define INF 1000000 /* 무한대 (연결이 없는 경우) */
typedef struct GraphType {
int n; // 정점의 개수
int weight[MAX_VERTICES][MAX_VERTICES];
} GraphType;
int distance[MAX_VERTICES];/* 시작정점으로부터의 최단경로 거리 */
int found[MAX_VERTICES]; /* 방문한 정점 표시 */
int choose(int distance[], int n, int found[])
{
int i, min, minpos;
min = INT_MAX;
minpos = -1;
for (i = 0; i < n; i++)
if (distance[i] < min && !found[i]) {
min = distance[i];
minpos = i;
}
return minpos;
}
void print_status(GraphType* g)
{
static int step = 1;
printf("STEP %d: ", step++);
printf("distance: ");
for (int i = 0; i < g->n; i++) {
if (distance[i] == INF)
printf(" * ");
else
printf("%2d ", distance[i]);
}
printf("\n");
printf(" found: ");
for (int i = 0; i < g->n; i++)
printf("%2d ", found[i]);
printf("\n\n");
}
//
void shortest_path(GraphType* g, int start)
{
int i, u, w;
for (i = 0; i < g->n; i++) /* 초기화 */
{
distance[i] = g->weight[start][i];
found[i] = FALSE;
}
found[start] = TRUE; /* 시작 정점 방문 표시 */
distance[start] = 0;
for (i = 0; i < g->n - 1; i++) {
print_status(g);
u = choose(distance, g->n, found);
found[u] = TRUE;
for (w = 0; w < g->n; w++)
if (!found[w])
if (distance[u] + g->weight[u][w] < distance[w])
distance[w] = distance[u] + g->weight[u][w];
}
}
int main(void)
{
GraphType g = { 7,
{{ 0, 7, INF, INF, 3, 10, INF },
{ 7, 0, 4, 10, 2, 6, INF },
{ INF, 4, 0, 2, INF, INF, INF },
{ INF, 10, 2, 0, 11, 9, 4 },
{ 3, 2, INF, 11, 0, INF, 5 },
{ 10, 6, INF, 9, INF, 0, INF },
{ INF, INF, INF, 4, 5, INF, 0 } }
};
shortest_path(&g, 0);
return 0;
}
시간 복잡도 : O(n제곱)
플로이드 최단 경로 알고리즘
플로이드의 최단 경로 알고리즘 : 그래프에 존재하는 모든 정점 사이의 최단 경로를 한 번에 모두 찾아주는 알고리즘
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define MAX_VERTICES 100
#define INF 1000000 /* 무한대 (연결이 없는 경우) */
typedef struct GraphType {
int n; // 정점의 개수
int weight[MAX_VERTICES][MAX_VERTICES];
} GraphType;
int A[MAX_VERTICES][MAX_VERTICES];
void printA(GraphType *g)
{
int i, j;
printf("===============================\n");
for (i = 0; i<g->n; i++) {
for (j = 0; j<g->n; j++) {
if (A[i][j] == INF)
printf(" * ");
else printf("%3d ", A[i][j]);
}
printf("\n");
}
printf("===============================\n");
}
void floyd(GraphType* g)
{
int i, j, k;
for (i = 0; i<g->n; i++)
for (j = 0; j<g->n; j++)
A[i][j] = g->weight[i][j];
printA(g);
for (k = 0; k<g->n; k++) {
for (i = 0; i<g->n; i++)
for (j = 0; j<g->n; j++)
if (A[i][k] + A[k][j] < A[i][j])
A[i][j] = A[i][k] + A[k][j];
printA(g);
}
}
int main(void)
{
GraphType g = { 7,
{{ 0, 7, INF, INF, 3, 10, INF },
{ 7, 0, 4, 10, 2, 6, INF },
{ INF, 4, 0, 2, INF, INF, INF },
{ INF, 10, 2, 0, 11, 9, 4 },
{ 3, 2, INF, 11, 0, INF, 5 },
{ 10, 6, INF, 9, INF, 0, INF },
{ INF, INF, INF, 4, 5, INF, 0 } }
};
floyd(&g);
return 0;
}
시간 복잡도 : O(n3제곱)
'자료구조와 알고리즘 ft. 수업 > [수업 정리] 자료구조' 카테고리의 다른 글
자료구조 대학 강의 정리 (0) | 2023.05.15 |
---|---|
자료구조 강의 내용 (0) | 2023.04.08 |
자료구조 워크플로 (0) | 2023.03.20 |
자료구조 1차시 (0) | 2023.03.05 |