Skip to content

Lecture 24. 자료구조 ​

개요 ​

핵심 질문

  • 각 자료구조는 어떤 문제를 해결하기 위해 설계되었는가?
  • 시간·공간 복잡도는 어떻게 분석하는가?
  • AI 알고리즘에서 각 자료구조는 어떻게 활용되는가?

학습 목표

  • 배열·연결 리스트·스택·큐·해시 테이블·트리·그래프의 정의와 연산 복잡도를 설명할 수 있다.
  • 각 자료구조의 장단점을 비교하고 적합한 상황을 선택할 수 있다.
  • AI 개발자 관점에서 각 자료구조가 어떤 시스템에 활용되는지 연결할 수 있다.

핵심 개념 ​

1. 복잡도 분석 ​

시간 복잡도 (Time Complexity)

입력 크기 nn에 따른 연산 횟수의 점근적 관계.

빅 오 표기법 (Big-O Notation)

함수의 점근적 상한 — 실행 시간이 이 이상은 커지지 않는다.

O(g(n))={f(n)∣∃c>0, n0: f(n)≤c⋅g(n) ∀n≥n0} O(g(n)) = \{f(n) \mid \exists c > 0,\ n_0:\ f(n) \leq c \cdot g(n)\ \forall n \geq n_0\}

표기이름예시
O(1)O(1)상수 시간해시 테이블 조회, 배열 인덱스 접근
O(log⁡n)O(\log n)로그 시간이진 탐색, BST 탐색
O(n)O(n)선형 시간배열 순회, 선형 탐색
O(nlog⁡n)O(n \log n)선형 로그병합 정렬, 힙 정렬
O(n2)O(n^2)이차 시간버블 정렬, 인접 행렬 탐색
O(2n)O(2^n)지수 시간완전 탐색(부분집합)
  • 빅 세타 Θ\Theta: 평균적인 실행 시간 (점근적 정확한 경계)
  • 빅 오메가 Ω\Omega: 점근적 하한

공간 복잡도 (Space Complexity)

프로그램 실행에 필요한 메모리 자원의 양. 시간-공간 트레이드오프가 자주 발생한다.

AI 개발자 관점

  • 모델 추론 시간은 주로 행렬 곱의 O(n2)O(n^2) 또는 O(n3)O(n^3) 복잡도에 지배된다.
  • Transformer Self-Attention의 시간 복잡도는 시퀀스 길이 nn에 대해 O(n2d)O(n^2 d) → 긴 시퀀스 처리 병목의 수학적 원인.
  • FlashAttention은 메모리 접근 패턴을 최적화하여 같은 O(n2)O(n^2)이지만 실제 속도를 크게 개선한다.

2. 배열 (Array) ​

정의

동일한 타입의 원소들이 연속된 메모리 공간에 순차적으로 저장되는 자료구조.

연산 복잡도

연산복잡도이유
인덱스 접근O(1)O(1)기준 주소 + 오프셋 계산
탐색O(n)O(n)최악의 경우 전체 순회
삽입/삭제 (중간)O(n)O(n)이후 원소 전부 이동
삽입/삭제 (끝)O(1)O(1)이동 불필요
  • 정적 배열: 크기가 컴파일 타임에 고정
  • 동적 배열: 런타임에 크기 변경 가능 (Python list, C++ vector) — 용량 초과 시 새 배열 할당 후 복사 (O(n)O(n) amortized O(1)O(1))

AI 개발자 심화

  • 텐서(Tensor): 다차원 배열의 일반화. NumPy ndarray, PyTorch Tensor가 모두 내부적으로 연속 메모리 배열.
  • 메모리 레이아웃: Row-major(C order) vs Column-major(Fortran order) — 행렬 곱 방향에 따라 캐시 히트율이 달라져 실제 연산 속도에 영향.
  • Stride: 텐서의 각 차원에서 다음 원소로 이동하기 위한 메모리 건너뜀 수. tensor.stride()로 확인 가능. View 연산은 데이터를 복사하지 않고 stride만 변경.
  • 임베딩 룩업: Embedding 레이어는 사실 임베딩 행렬(2D 배열)에서 행 인덱스로 O(1)O(1) 접근하는 배열 연산.

3. 연결 리스트 (Linked List) ​

정의

노드(데이터 + 다음 노드 포인터)들이 포인터로 연결된 자료구조. 메모리가 불연속적으로 배치된다.

종류

종류특징
단일 연결 리스트단방향 탐색, 각 노드에 next 포인터 1개
이중 연결 리스트양방향 탐색, prev + next 포인터 2개
환형 연결 리스트꼬리가 헤드를 가리켜 원형 구성

연산 복잡도

연산복잡도비고
인덱스 접근O(n)O(n)헤드부터 순차 탐색
탐색O(n)O(n)
삽입/삭제 (위치 알 때)O(1)O(1)포인터 변경만
삽입/삭제 (위치 탐색 포함)O(n)O(n)

배열 vs 연결 리스트

배열연결 리스트
메모리연속 (캐시 친화)불연속 (캐시 비효율)
인덱스 접근O(1)O(1)O(n)O(n)
삽입/삭제O(n)O(n)O(1)O(1) (위치 알 때)
크기 변경어려움유연

AI 개발자 심화

  • 동적 계산 그래프: PyTorch의 자동 미분은 내부적으로 연산 노드들을 연결 리스트 구조로 관리하여 역전파 경로를 추적한다.
  • KV Cache: LLM 추론 시 이전 토큰의 Key·Value를 캐싱할 때 시퀀셜 메모리 구조로 관리.

4. 스택 (Stack) ​

정의

한쪽 끝(top)에서만 삽입·삭제가 가능한 후입선출(LIFO, Last-In First-Out) 자료구조.

핵심 연산

  • Push: top에 원소 삽입 O(1)O(1)
  • Pop: top에서 원소 제거 O(1)O(1)
  • Peek: top 원소 조회 O(1)O(1)

주요 활용

  • 함수 호출 스택(Call Stack): 재귀 함수 실행 순서 관리
  • 수식 파싱: 괄호 검사, 후위 표기법 변환
  • DFS 구현: 방문 스택
  • 되돌리기(Undo) 기능

AI 개발자 심화

  • 역전파 실행 순서: 순전파 중 각 연산의 중간 결과와 로컬 그래디언트를 스택 구조로 저장하고, 역방향으로 순서대로 꺼내며 연쇄 법칙 적용.
  • 재귀 → 스택 변환: 깊은 재귀로 구현된 트리 순회나 DFS는 콜 스택 오버플로 위험이 있으므로 명시적 스택으로 변환하여 처리.

5. 큐 (Queue) ​

정의

한쪽(rear)으로 삽입, 다른 쪽(front)으로 삭제하는 선입선출(FIFO, First-In First-Out) 자료구조.

핵심 연산

  • Enqueue: rear에 원소 삽입 O(1)O(1)
  • Dequeue: front에서 원소 제거 O(1)O(1)

변형

종류특징
원형 큐배열 기반, 양 끝을 원형으로 연결하여 공간 재사용
덱 (Deque)양쪽에서 삽입·삭제 모두 가능
우선순위 큐우선순위가 높은 원소를 먼저 처리, 힙으로 구현 O(log⁡n)O(\log n)

주요 활용

  • BFS 구현
  • 작업 스케줄링, 버퍼(네트워크 패킷, 프린터 대기열)
  • 슬라이딩 윈도우

AI 개발자 심화

  • 빔 서치 (Beam Search): 텍스트 생성에서 상위 kk개 후보를 유지하며 탐색. 우선순위 큐로 각 스텝에서 확률이 높은 토큰 시퀀스를 효율적으로 관리.
  • 데이터 로더 버퍼: PyTorch DataLoader는 내부적으로 큐를 사용하여 CPU 전처리와 GPU 연산을 파이프라인화한다.
  • 경험 재생 버퍼 (Replay Buffer): DQN에서 과거 경험 (s,a,r,s′)(s, a, r, s')을 원형 큐에 저장하고 랜덤 샘플링하여 상관관계 제거.

6. 해시 테이블 (Hash Table) ​

정의

키(Key)를 해시 함수로 변환하여 배열의 인덱스에 대응시키는 자료구조.

index=h(key)mod  M \text{index} = h(\text{key}) \mod M

해시 함수 (Hash Function)

임의 길이의 입력 → 고정 길이의 해시 값으로 변환하는 단방향 함수.

좋은 해시 함수의 조건:

  • 결정론적: 같은 입력 → 항상 같은 출력
  • 균등 분포: 해시 값이 버킷 전체에 고루 분포
  • 빠른 계산: O(1)O(1) 또는 입력 길이에 비례

연산 복잡도

연산평균최악 (충돌 심할 때)
탐색O(1)O(1)O(n)O(n)
삽입O(1)O(1)O(n)O(n)
삭제O(1)O(1)O(n)O(n)

해시 충돌 해결

방법설명특징
체이닝 (Chaining)같은 버킷에 연결 리스트로 연결구현 단순, 메모리 오버헤드
개방 주소법다른 빈 버킷에 저장캐시 친화적
선형 조사법다음 인덱스 순차 탐색군집화 문제
이차 조사법제곱 간격으로 탐색군집화 완화
이중 해싱두 번째 해시 함수로 간격 결정군집화 최소화

부하율 (Load Factor)

α=nM(n:저장된 원소 수, M:버킷 수) \alpha = \frac{n}{M} \quad (n: \text{저장된 원소 수},\ M: \text{버킷 수})

α\alpha가 커질수록 충돌 확률 증가. 일반적으로 α>0.7\alpha > 0.7이면 리해싱(rehashing).

AI 개발자 심화

  • 토크나이저 어휘 사전: GPT, BERT의 토크나이저는 토큰 문자열 → 정수 ID 매핑에 해시맵을 사용. 수십만 개 어휘에서 O(1)O(1) 인코딩/디코딩.
  • 임베딩 룩업 테이블: nn.Embedding은 정수 인덱스 → 임베딩 벡터의 해시 테이블 기반 매핑.
  • 특성 해싱 (Feature Hashing): 고차원 범주형 특성을 해시로 고정 차원 벡터에 매핑 — 메모리 절약, 충돌 허용.
  • 중복 제거: 데이터 전처리 중 중복 샘플 제거 시 해시 기반 set 자료구조 활용.

7. 트리 (Tree) ​

정의

노드(Node)와 간선(Edge)으로 구성된 계층적 자료구조. 사이클이 없는 연결 그래프.

기본 용어

용어설명
루트 노드최상위 노드, 부모 없음
리프 노드최하위 노드, 자식 없음
깊이(Depth)루트에서 해당 노드까지의 간선 수
높이(Height)루트에서 가장 깊은 리프까지의 간선 수
차수(Degree)자식 노드의 수

트리의 순회

방법순서특징
전위(Pre-order)루트 → 왼쪽 → 오른쪽트리 복사, 직렬화
중위(In-order)왼쪽 → 루트 → 오른쪽BST에서 오름차순 출력
후위(Post-order)왼쪽 → 오른쪽 → 루트하위 노드 먼저 처리
레벨(BFS)레벨 순서최단 경로, BFS 탐색

주요 트리 종류

이진 탐색 트리 (BST)

  • 왼쪽 서브트리: 루트보다 작은 값
  • 오른쪽 서브트리: 루트보다 큰 값
  • 탐색·삽입·삭제: 평균 O(log⁡n)O(\log n), 최악(편향) O(n)O(n)

힙 (Heap)

완전 이진 트리 기반. 우선순위 큐 구현에 사용.

  • 최대 힙: 부모 ≥ 자식
  • 최소 힙: 부모 ≤ 자식
  • 삽입·삭제: O(log⁡n)O(\log n), 최대·최솟값 조회: O(1)O(1)

자가 균형 트리 (AVL, Red-Black Tree)

삽입·삭제 후에도 트리 높이 O(log⁡n)O(\log n) 유지.

  • Red-Black 트리: 삽입·삭제 O(log⁡n)O(\log n), 색상 규칙으로 균형 유지
  • 실제 활용: 대부분의 언어 표준 라이브러리의 정렬된 맵(C++ std::map, Java TreeMap)

B-트리 / B+트리

  • 하나의 노드에 여러 키를 저장하는 다진 탐색 트리
  • 디스크 I/O 최소화 — 한 번의 블록 읽기로 많은 키 비교 가능
  • B+트리: 실제 데이터를 모두 리프 노드에 저장, 리프 노드를 연결 리스트로 연결 → 범위 검색 효율적

트라이 (Trie)

문자열을 문자 단위로 노드에 저장하는 트리. 문자열 탐색 O(L)O(L) (LL: 문자열 길이).

AI 개발자 심화

  • 결정 트리 (Decision Tree): 트리 구조로 분류·회귀를 수행. 각 노드에서 특성 기준으로 분기. XGBoost·LightGBM·CatBoost 모두 앙상블 결정 트리.
  • MCTS (Monte Carlo Tree Search): AlphaGo·AlphaZero에서 사용. 게임 상태를 트리 노드로 표현하고 UCB(Upper Confidence Bound)로 탐험·활용 균형.

UCB(v)=wini+cln⁡Nni \text{UCB}(v) = \frac{w_i}{n_i} + c\sqrt{\frac{\ln N}{n_i}}

  • wiw_i: 노드 ii의 누적 보상, nin_i: 방문 횟수, NN: 부모 방문 횟수, cc: 탐험 계수
  • 토크나이저 트라이: BPE(Byte Pair Encoding) 토크나이저 구현에 트라이를 활용하여 빠른 문자열 매칭.
  • 벡터 DB 인덱스 (HNSW): 계층적 그래프 구조로 근사 최근접 이웃 탐색 수행 — 트리와 그래프의 혼합 구조.

8. 그래프 (Graph) ​

정의

정점(Vertex)과 간선(Edge)으로 구성된 자료구조. 트리는 그래프의 특수 케이스(사이클 없는 연결 그래프).

G=(V,E) G = (V, E)

그래프의 종류

종류설명
무방향 그래프간선에 방향 없음
방향 그래프 (DAG 포함)간선에 방향 있음
가중치 그래프간선에 비용(가중치) 부여
연결 그래프임의의 두 정점 사이에 경로 존재
DAGDirected Acyclic Graph — 방향 있고 사이클 없음

그래프 표현 방식

인접 행렬: O(V2)O(V^2) 공간, 간선 존재 확인 O(1)O(1)

Aij={wij(i,j)∈E0otherwise A_{ij} = \begin{cases} w_{ij} & (i, j) \in E \\ 0 & \text{otherwise} \end{cases}

인접 리스트: O(V+E)O(V + E) 공간, 희소 그래프에 효율적

주요 탐색 알고리즘

깊이 우선 탐색 (DFS)

스택(또는 재귀)을 사용하여 최대한 깊이 탐색.

  • 시간 복잡도: O(V+E)O(V + E)
  • 활용: 사이클 탐지, 위상 정렬, 연결 요소 탐색

너비 우선 탐색 (BFS)

큐를 사용하여 레벨 단위로 탐색.

  • 시간 복잡도: O(V+E)O(V + E)
  • 활용: 비가중치 그래프 최단 경로

최단 경로 알고리즘

다익스트라 알고리즘 (단일 출발, 비음수 가중치):

d[v]=min⁡u∈visited(d[u]+w(u,v)) d[v] = \min_{u \in \text{visited}} \left(d[u] + w(u, v)\right)

우선순위 큐 사용 시 시간 복잡도: O((V+E)log⁡V)O((V + E)\log V)

벨만-포드 알고리즘: 음수 가중치 허용, O(VE)O(VE)

플로이드-워셜: 모든 쌍 최단 경로, O(V3)O(V^3)

위상 정렬 (Topological Sort)

DAG에서 모든 간선 (u,v)(u, v)에 대해 uu가 vv보다 먼저 오는 순서.

  • Kahn 알고리즘 (BFS 기반): 진입 차수가 0인 정점부터 처리
  • 시간 복잡도: O(V+E)O(V + E)

AI 개발자 심화

  • 계산 그래프 (Computational Graph): 신경망의 순전파·역전파는 DAG 위에서 이루어진다. PyTorch의 autograd 엔진은 DAG를 역방향 위상 정렬 순서로 순회하며 그래디언트를 계산한다.
  • GNN (Graph Neural Network): 그래프 데이터(소셜 네트워크, 분자 구조, 지식 그래프)를 직접 처리하는 신경망. 각 노드가 이웃 노드의 특성을 집계(Message Passing)하여 표현 업데이트.

hv(k)=UPDATE ⁣(hv(k−1), AGGREGATE ⁣({hu(k−1):u∈N(v)})) \mathbf{h}_v^{(k)} = \text{UPDATE}\!\left(\mathbf{h}_v^{(k-1)},\ \text{AGGREGATE}\!\left(\{\mathbf{h}_u^{(k-1)} : u \in \mathcal{N}(v)\}\right)\right)

  • 지식 그래프 (Knowledge Graph): 엔티티(노드)와 관계(간선)로 구성. RAG 시스템에서 구조화된 외부 지식으로 활용.
  • 분자 설계: 원자(노드)·결합(간선)을 그래프로 표현 → GNN으로 물성 예측·신약 후보 생성.
  • 추천 시스템: 사용자-아이템 이분 그래프에 GNN 적용 → 협업 필터링.

9. 정렬 알고리즘 ​

주요 정렬 알고리즘 비교

알고리즘평균최악공간안정
버블 정렬O(n2)O(n^2)O(n2)O(n^2)O(1)O(1)✓
삽입 정렬O(n2)O(n^2)O(n2)O(n^2)O(1)O(1)✓
선택 정렬O(n2)O(n^2)O(n2)O(n^2)O(1)O(1)✗
퀵 정렬O(nlog⁡n)O(n\log n)O(n2)O(n^2)O(log⁡n)O(\log n)✗
병합 정렬O(nlog⁡n)O(n\log n)O(nlog⁡n)O(n\log n)O(n)O(n)✓
힙 정렬O(nlog⁡n)O(n\log n)O(nlog⁡n)O(n\log n)O(1)O(1)✗
계수 정렬O(n+k)O(n+k)O(n+k)O(n+k)O(k)O(k)✓

정렬의 비교 기반 하한: Ω(nlog⁡n)\Omega(n\log n) (결정 트리 논증).

AI 개발자 심화

  • Top-K 추출: LLM의 Top-K 샘플링, 추천 시스템의 Top-K 아이템 추출에서 전체 정렬 대신 힙을 이용한 부분 정렬 O(nlog⁡k)O(n\log k) 사용.
  • Argsort: PyTorch torch.argsort는 인덱스 기반 정렬 — 어텐션 점수 랭킹, 특성 중요도 정렬에 활용.

수식 정리 ​

시간 복잡도 빅 오 정의

f(n)=O(g(n))⇔∃c,n0: f(n)≤c⋅g(n), ∀n≥n0 f(n) = O(g(n)) \Leftrightarrow \exists c, n_0:\ f(n) \leq c \cdot g(n),\ \forall n \geq n_0

주요 자료구조 복잡도 요약

자료구조탐색삽입삭제공간
배열O(n)O(n)O(n)O(n)O(n)O(n)O(n)O(n)
해시 테이블O(1)O(1) avgO(1)O(1) avgO(1)O(1) avgO(n)O(n)
이진 탐색 트리O(log⁡n)O(\log n) avgO(log⁡n)O(\log n) avgO(log⁡n)O(\log n) avgO(n)O(n)
힙O(n)O(n)O(log⁡n)O(\log n)O(log⁡n)O(\log n)O(n)O(n)
그래프 (인접 리스트)O(V+E)O(V+E)O(1)O(1)O(E)O(E)O(V+E)O(V+E)

Self-Attention 복잡도

O(n2d)(n:시퀀스 길이, d:차원) O(n^2 d) \quad (n: \text{시퀀스 길이},\ d: \text{차원})

MCTS UCB

UCB(v)=wini+cln⁡Nni \text{UCB}(v) = \frac{w_i}{n_i} + c\sqrt{\frac{\ln N}{n_i}}

GNN 메시지 패싱

hv(k)=UPDATE ⁣(hv(k−1), ⨁u∈N(v)hu(k−1)) \mathbf{h}_v^{(k)} = \text{UPDATE}\!\left(\mathbf{h}_v^{(k-1)},\ \bigoplus_{u \in \mathcal{N}(v)} \mathbf{h}_u^{(k-1)}\right)

다익스트라 갱신 조건

d[v]>d[u]+w(u,v)⇒d[v]←d[u]+w(u,v) d[v] > d[u] + w(u,v) \Rightarrow d[v] \leftarrow d[u] + w(u,v)