알고리즘 기초 — 탐색, 정렬, 효율성
자료구조에 담긴 데이터를 '어떻게' 가장 효율적으로 처리할 것인가에 대한 해답입니다. 수백만 개의 데이터를 검색하고 정렬하는 과정에서 발생하는 연산 비용(시간 복잡도)을 줄이는 사고방식을 훈련합니다.
학습 목표
O(1), O(n), O(n²), O(log n)을 이해한다.알고리즘 (Algorithm) 이란?
알고리즘은 주어진 문제를 해결하기 위한 명확하고 단계적인 절차입니다. 우리가 배운 순차(위에서 아래로), 조건(if), 반복(for, while) 구조를 레고 블록처럼 조합하여 '가장 빠르고 정확하게 데이터를 가공하는 방법'을 설계하는 것입니다.
자료구조는 데이터를 "어떻게 담아둘 것인가?" (그릇의 종류)에 대한 고민이라면, 알고리즘은 그 담긴 데이터를 "어떻게 요리할 것인가?" (레시피)에 대한 고민입니다.
선형 탐색 vs 이진 탐색
선형 탐색(Linear Search)은 배열의 처음부터 끝까지 하나씩 확인하는 단순한 방법입니다. 반면, 이진 탐색(Binary Search)은 데이터가 미리 정렬되어 있다는 조건 하에 가운데를 찔러보고 절반씩 범위를 버려나가는 매우 빠른 탐색 기법입니다.
int binarySearch(int arr[], int size, int target) { int left = 0; int right = size - 1; while (left <= right) { int mid = (left + right) / 2; if (arr[mid] == target) return mid; // 찾음 if (arr[mid] < target) left = mid + 1; // 오른쪽 절반으로 축소 else right = mid - 1; // 왼쪽 절반으로 축소 } return -1; // 못 찾음 }
기초 정렬 (버블 / 선택 / 삽입)
무작위 데이터를 순서대로(오름차순/내림차순) 나열하는 것을 정렬(Sort)이라고 합니다. 정렬이 되어 있어야 위에서 배운 강력한 '이진 탐색'을 사용할 수 있습니다.
인접한 두 개의 원소를 비교하며, 더 큰 값을 계속 뒤로 밀어내는 방식입니다. 거품이 수면 위로 올라가는 모습과 닮았다 하여 버블 정렬이라 부릅니다.
void bubbleSort(int arr[], int size) { for (int i = 0; i < size - 1; i++) { // 루프가 돌 때마다 제일 큰 값이 맨 뒤로 고정되므로 끝 범위를 1씩 줄임 for (int j = 0; j < size - 1 - i; j++) { if (arr[j] > arr[j + 1]) { // 오름차순 (앞이 더 크면 교환) int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } }
- 선택 정렬 (Selection Sort) : 남은 데이터 중 가장 작은 값을 '선택'해서 맨 앞의 값과 교체하는 방식입니다.
- 삽입 정렬 (Insertion Sort) : 현재 값을 뽑아서, 이미 정렬되어 있는 앞쪽 배열 공간 중 '적절한 위치에 끼워 넣는(삽입)' 방식입니다. 카드를 정리할 때 많이 쓰는 방법입니다.
시간 복잡도 (Big-O Notation)
알고리즘의 성능은 "몇 초가 걸리는가?"로 측정하지 않습니다. 컴퓨터 성능에 따라 달라지기 때문입니다. 대신 "데이터 개수(n)가 늘어날 때 연산 횟수가 어떻게 증가하는가?"를 표현하는 표기법이 바로 Big-O입니다.
- O(1) : 데이터가 100만 개든 1개든 동일한 속도 (예:
arr[5]인덱스 접근) - O(log n) : 절반씩 쪼개며 검색하여 매우 빠름 (예: 이진 탐색)
- O(n) : 데이터 개수만큼 비례해서 시간 증가 (예: 선형 탐색, for문 1번)
- O(n²) : for문이 중첩되어 최악의 경우 매우 느림 (예: 버블, 선택 정렬)
STEP 16 최종 프로젝트
학생 성적 종합 분석 및 정렬 시스템
배열에 들어있는 학생들의 성적(점수)을 종합적으로 분석하는 알고리즘 세트를 구성해 봅니다. 하나의 main.c에서 여러 알고리즘 함수들을 호출하며 결과를 조합해 보세요.
- [1] 기초 연산 :
int scores[7] = {85, 72, 91, 64, 78, 95, 88};에서 합계와 평균 계산. - [2] 탐색 연산 : O(n) 선형 탐색을 이용해 최고 점수와 최저 점수를 도출.
- [3] 정렬 연산 : 버블 정렬(Bubble Sort)을 이용하여 데이터를 오름차순으로 정렬하여 출력.
- [4] 검색 연산 (옵션) : 정렬된 배열을 이용해 O(log n) 이진 탐색으로 88점의 인덱스를 찾아보기.
STEP 16 완료 체크리스트
알고리즘을 잘 짠다는 것은 단순히 코드를 짧게 쓰는 것이 아니라, 컴퓨터가 연산하는 횟수를 기하급수적으로 줄이는 것입니다. 10억 개의 데이터에서 무작정 찾는 것과 이진 탐색으로 단 30번 만에 찾는 것은 하늘과 땅 차이입니다. 이제 자료구조와 알고리즘의 기초를 다졌으니, C언어의 꽃이자 최종 보스, 고급 포인터(함수 포인터와 이중 포인터)의 세계로 넘어갑니다!