
프로그래밍을 하다 보면 데이터를 저장하고 처리하는 일이 정말 많다. 이때 단순히 변수를 여러 개 선언해서 쓰는 방식으로는 복잡한 문제를 해결할 수 없다. 그래서 등장한 것이 바로 자료구조(Data Structures)다.
자료구조는 데이터를 컴퓨터 메모리에 효율적으로 저장하고 다룰 수 있도록 만들어진 특화된 형식이다. 다시 말해, 데이터를 정리하고 저장하는 방법을 의미하며, 프로그램의 성능과 직결되는 중요한 개념이다.
자료구조는 거의 모든 소프트웨어 시스템에서 사용된다. 웹 서비스, 운영체제, 이미지 편집 툴, 게임, 데이터베이스 등 어디서나 자료구조는 필수다. 종류로는 배열, 연결 리스트, 큐, 스택, 트리, 그래프 등 다양한 형태가 존재한다.
자료구조는 단순히 데이터를 저장하는 데서 끝나지 않는다. 효율적인 알고리즘 설계의 기반이 되는 요소이기 때문이다. 어떤 문제를 해결할 때 적절한 자료구조를 선택하지 않으면, 코드가 복잡해지고 실행 속도가 느려질 수 있다.
예를 들어 대기열 같은 구조가 필요한 작업에는 큐(Queue)를, 되돌리기 같은 기능에는 스택(Stack)을 사용하는 것이 자연스럽다. 이렇게 각 자료구조는 각자의 사용 목적과 특성이 있으며, 이를 잘 활용하는 것이 효율적인 프로그래밍의 핵심이다.
정리하자면, 자료구조는 다음과 같은 이유로 중요하다:
프로그래밍을 시작할 때 가장 먼저 접하게 되는 기본 자료구조 5가지를 정리해보았다.
배열은 동일한 타입의 데이터를 연속된 메모리 공간에 저장하는 구조다. 인덱스를 이용해 원하는 위치의 값을 바로 접근할 수 있어 매우 빠르다.
arr = [1, 2, 3, 4]
print(arr[2]) # 결과: 3
배열은 고정된 크기를 가지기 때문에 유연성은 떨어지지만, 속도 면에서는 효율적이다.
연결 리스트는 각 데이터를 노드(Node)라는 단위로 저장하며, 각 노드는 다음 노드를 가리키는 포인터를 포함한다. 배열과 다르게 크기를 동적으로 조절할 수 있는 것이 장점이다.
class Node:
def __init__(self, data):
self.data = data
self.next = None
연결 리스트는 삽입과 삭제가 빠르지만, 인덱스를 이용한 접근은 느리다.
스택은 후입선출(Last In First Out, LIFO) 구조다. 가장 나중에 들어온 데이터가 가장 먼저 나간다. 브라우저의 되돌리기 기능이나 재귀 호출 등에 활용된다.
stack = []
stack.append(1)
stack.append(2)
print(stack.pop()) # 결과: 2
큐는 선입선출(First In First Out, FIFO) 구조다. 먼저 들어온 데이터가 먼저 나간다. 작업 스케줄링, 프린터 대기열 등에 사용된다.
from collections import deque
queue = deque()
queue.append(1)
queue.append(2)
print(queue.popleft()) # 결과: 1
해시 테이블은 키(Key)를 해시 함수에 넣어 인덱스를 계산하고, 그 위치에 값을 저장하는 구조다. 빠른 삽입, 삭제, 검색이 가능하다.
hash_table = {}
hash_table["apple"] = 10
print(hash_table["apple"]) # 결과: 10
단점은 해시 충돌이 발생할 수 있다는 점인데, 체이닝(chaining)이나 오픈 어드레싱(open addressing) 등의 기법으로 해결한다.
자료구조는 단순한 개념 같지만, 문제 해결 능력을 결정짓는 매우 중요한 요소다. 이 글에서는 배열, 연결 리스트, 스택, 큐, 해시 테이블을 소개했지만, 이 외에도 트리, 힙, 그래프 등 다양한 고급 자료구조들이 존재한다. 앞으로 자료구조 하나하나를 깊이 있게 다루어볼 예정이다.