728x90
반응형
자료구조 관련 내용은 하단 포스트를 참고해주세요.
2024.12.14 - [Computer Science/자료구조 & 알고리즘] - [자료구조 & 알고리즘] 자료구조 개념 총정리 (향후 내용추가)
[자료구조 & 알고리즘] 자료구조 개념 총정리 (향후 내용추가)
1. 선형 리스트 (Linear List)설명: 데이터를 연속된 메모리 공간에 저장하며, 순서를 보장하는 자료구조.특징:인덱스를 통해 O(1) 시간 복잡도로 접근.삽입/삭제는 O(n)로 비효율적.필수 알고리즘:이
rnasterofmysea.tistory.com
0. 이진 트리 (Binary Tree)
- 설명: 각 노드가 최대 두 개의 자식을 가지는 계층적 자료구조.
- 특징:
- 전위, 중위, 후위 순회 가능.
- 필수 알고리즘:
- 트리 순회:
- 전위, 중위, 후위 탐색.
- 최대 깊이 계산:
- 트리의 깊이 계산.
- 트리 순회:
1. 이진 검색 트리(Binary Search Tree, BST)란?
이진 검색 트리는 이진 트리의 한 종류로, 특정 규칙을 따릅니다.
이진 검색 트리의 규칙
- 왼쪽 자식 노드의 값은 부모 노드의 값보다 작습니다.
- 오른쪽 자식 노드의 값은 부모 노드의 값보다 큽니다.
예시로 위 트리를 다시 살펴봅시다.
10
/ \
5 15
/ \ \
3 7 20
- 부모 노드 10: 왼쪽 자식(5)은 10보다 작고, 오른쪽 자식(15)은 10보다 큽니다.
- 부모 노드 5: 왼쪽 자식(3)은 5보다 작고, 오른쪽 자식(7)은 5보다 큽니다.
이 규칙 덕분에 탐색, 삽입, 삭제 등의 연산이 효율적으로 수행됩니다.
2. 이진 검색 트리의 주요 연산
1) 탐색(Search)
값이 트리에 있는지 확인하는 과정입니다.
탐색은 루트 노드부터 시작해서 다음과 같은 방식으로 진행됩니다.
- 찾고자 하는 값이 현재 노드의 값과 같으면 탐색 종료.
- 찾고자 하는 값이 현재 노드의 값보다 작으면 왼쪽 서브트리로 이동.
- 찾고자 하는 값이 현재 노드의 값보다 크면 오른쪽 서브트리로 이동.
탐색 예제 코드 (C언어):
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* left;
struct Node* right;
} Node;
Node* search(Node* root, int key) {
if (root == NULL || root->data == key)
return root; // 값이 없거나 찾은 경우
if (key < root->data)
return search(root->left, key); // 왼쪽 서브트리 탐색
return search(root->right, key); // 오른쪽 서브트리 탐색
}
2) 삽입(Insertion)
새로운 값을 트리에 추가하는 과정입니다.
삽입할 위치를 찾기 위해 탐색을 수행한 뒤, 해당 위치에 새 노드를 추가합니다.
삽입 규칙
- 삽입할 값이 현재 노드보다 작으면 왼쪽으로 이동.
- 삽입할 값이 현재 노드보다 크면 오른쪽으로 이동.
- 알맞은 위치에 도달하면 노드를 추가.
삽입 예제 코드 (C언어):
Node* createNode(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}
Node* insert(Node* root, int data) {
if (root == NULL)
return createNode(data); // 새 노드 생성
if (data < root->data)
root->left = insert(root->left, data); // 왼쪽 서브트리로 이동
else if (data > root->data)
root->right = insert(root->right, data); // 오른쪽 서브트리로 이동
return root;
}
3) 삭제(Deletion)
트리에서 값을 삭제하는 과정입니다. 삭제하려는 노드의 자식 노드 개수에 따라 다르게 처리합니다.
- 자식이 없는 경우: 노드를 그냥 삭제합니다.
- 자식이 하나인 경우: 해당 노드를 삭제하고, 자식을 부모 노드에 연결합니다.
- 자식이 두 개인 경우: 오른쪽 서브트리에서 가장 작은 값을 가진 노드로 대체하고, 해당 노드를 삭제합니다.
삭제 예제 코드 (C언어):
Node* findMin(Node* root) {
while (root->left != NULL)
root = root->left; // 최솟값 노드 탐색
return root;
}
Node* deleteNode(Node* root, int key) {
if (root == NULL) return root;
if (key < root->data)
root->left = deleteNode(root->left, key); // 왼쪽 서브트리에서 삭제
else if (key > root->data)
root->right = deleteNode(root->right, key); // 오른쪽 서브트리에서 삭제
else {
if (root->left == NULL) {
Node* temp = root->right;
free(root);
return temp;
} else if (root->right == NULL) {
Node* temp = root->left;
free(root);
return temp;
}
Node* temp = findMin(root->right);
root->data = temp->data; // 최솟값 노드로 대체
root->right = deleteNode(root->right, temp->data);
}
return root;
}
3. 이진 검색 트리의 시간 복잡도
연산 평균 시간 복잡도 최악 시간 복잡도 (편향 트리)
탐색 | O(log n) | O(n) |
삽입 | O(log n) | O(n) |
삭제 | O(log n) | O(n) |
4. 생성, 삽입, 삭제, 출력 전체 코드
#include <stdio.h>
#include <stdlib.h>
// 노드 구조체 정의
typedef struct Node {
int data;
struct Node* left;
struct Node* right;
} Node;
// 노드 생성 함수
Node* createNode(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}
// 탐색 함수
Node* search(Node* root, int key) {
if (root == NULL || root->data == key)
return root;
if (key < root->data)
return search(root->left, key);
return search(root->right, key);
}
// 삽입 함수
Node* insert(Node* root, int data) {
if (root == NULL)
return createNode(data);
if (data < root->data)
root->left = insert(root->left, data);
else if (data > root->data)
root->right = insert(root->right, data);
return root;
}
// 최소값 찾기 함수 (삭제에 사용)
Node* findMin(Node* root) {
while (root->left != NULL)
root = root->left;
return root;
}
// 삭제 함수
Node* deleteNode(Node* root, int key) {
if (root == NULL) return root;
if (key < root->data)
root->left = deleteNode(root->left, key);
else if (key > root->data)
root->right = deleteNode(root->right, key);
else {
if (root->left == NULL) {
Node* temp = root->right;
free(root);
return temp;
} else if (root->right == NULL) {
Node* temp = root->left;
free(root);
return temp;
}
Node* temp = findMin(root->right);
root->data = temp->data;
root->right = deleteNode(root->right, temp->data);
}
return root;
}
// 중위 순회 함수
void inorderTraversal(Node* root) {
if (root != NULL) {
inorderTraversal(root->left);
printf("%d ", root->data);
inorderTraversal(root->right);
}
}
// 메인 함수
int main() {
Node* root = NULL;
// 삽입 연산 테스트
int values[] = {50, 30, 20, 40, 70, 60, 80};
for (int i = 0; i < 7; i++) {
root = insert(root, values[i]);
}
// 삽입 후 출력
printf("삽입 후 중위 순회 결과: ");
inorderTraversal(root);
printf("\n");
// 검색 연산 테스트
Node* searchResult = search(root, 40);
if (searchResult != NULL)
printf("검색 결과 (40): 찾음\n");
else
printf("검색 결과 (40): 찾지 못함\n");
// 삭제 연산 테스트
root = deleteNode(root, 50);
printf("50 삭제 후 중위 순회 결과: ");
inorderTraversal(root);
printf("\n");
return 0;
}
5. 이진 검색 트리의 장단점
장점:
- 탐색, 삽입, 삭제가 평균적으로 빠릅니다.
- 중위 순회를 통해 데이터를 정렬된 순서로 출력할 수 있습니다.
단점:
- 트리가 편향되면 시간 복잡도가 O(n)으로 증가합니다.
- 균형을 유지하기 위해 AVL 트리나 레드-블랙 트리 같은 균형 트리가 필요할 수 있습니다.
💡 도움이 되셨다면 댓글과 공감 부탁드립니다! 😊
📌 더 많은 알고리즘 풀이와 프로그래밍 자료는 블로그에서 확인하세요!
✉️ 문의나 피드백은 댓글이나 이메일로 남겨주세요.
728x90
반응형
'Computer Science > 자료구조 & 알고리즘' 카테고리의 다른 글
[자료구조 & 알고리즘] 힙(Heap)으로 우선순위 큐 구현하기 (feat. Lazy Deletion) (0) | 2025.02.25 |
---|---|
[자료구조 & 알고리즘] AVL 트리 (feat. 균형 이진 트리) (0) | 2025.02.13 |
[자료구조 & 알고리즘] 해시 테이블(Hash Table) (0) | 2025.02.05 |
[자료구조 & 알고리즘] 이분 탐색 (Binary Search) (0) | 2025.02.03 |
[자료구조 & 알고리즘] 그리디 알고리즘(Greedy Algorithm) (0) | 2025.02.02 |