3주차는 자료구조에 대한 내용을 학습했습니다.
다양한 자료구조의 구조와 동작 원리를 이해하고,
python 코드로 직접 구현해 보며 이들이 알고리즘에 어떻게 적용되는지 익혔습니다.
⚠️본 글은 부트캠프 수업 내용을 기반으로 한 개인 학습 기록입니다.
✅ 자료구조
1. 정의
📌 자료구조란?
데이터를 저장하고 효율적으로 다루기 위한 구조와 연산의 집합이다
2. 주요 연산
- 읽기(Read)
- 쓰기(Write)
- 삽입(Insert)
- 삭제(Delete)
- 탐색(Search)
3. 알고리즘
- 정의: 입력 데이터를 가지고 원하는 출력을 만들어내는 논리적 절차
- 9세기 페르시아 수학자 '알 콰리즈미'의 이름에서 유래되었다
4. 알고리즘의 시간 복잡도 (Time Complexity)
- 입력에 대한 기본 연산 횟수
- 모든 입력의 평균을 구하는 것이 정확하나, 계산이 복잡하므로 최악의 경우를 사용
- 다른 입력에 대해서 최악의 경우보다 더 많은 시간이 걸리지 않음을 보장한다는 장점이 있다
💥 최악의 경우 (Worst Case)란? - 조건문이 가장 많이 참이 되는 경우
- 가장 많은 갱신이 일어나는 경우
5. 빅오 표기법 (Big-O Notation)
1) 개념
- 최고차항만으로 시간 복잡도를 간단히 표현
- 함수의 증가율을 결정하는 가장 중요한 항에 집중
- ‘Big’은 대략적으로라는 의미
2) 표기 규칙
- 최고차항만 남긴다
- 계수는 생략한다
- O()로 감싼다
- T₁(n) = 2n - 1 → O(n)
- T₂(n) = 4n + 1 → O(n)
- T₃(n) = (2/3)n² - (2/3)n + 1 → O(n²)
3) 표기 예시
- O(1): 상수 시간
- 입력 크기(n)와 무관하게 항상 같은 시간에 처리
- 배열의 인덱스 접근에 사용
- 아무리 n이 커져도 연산 횟수는 1번
- O(log n): 로그 시간
- 입력 크기를 계속 반으로 나눈다
- n이 커질수록 증가하긴 하지만 느리게 증가
- O(n): 선형 시간
- 입력의 모든 요소를 한 번씩 처리
- 리스트 전체를 순회하면서 합을 구할 때 사용
- n이 2배면 연산도 2배
- O(n²): 이차 시간
- 입력마다 중첩 반복 → 총 n x n 번 수행
- 버블 정렬, 이중 for문에 사용
- 입력이 커질수록 급격히 느려짐
6. 순차적 자료구조
📌배열, 리스트, 큐, 스택
- 배열 (Array)
- 데이터들이 순차적으로 저장되는 가장 기본적인 구조
- 인덱스를 통해 특정 위치의 값에 O(1) 시간에 접근 가능
- 읽기(Read)와 쓰기(Write)를 지원한다
- 리스트 (List)
- 파이썬의 리스트는 동적 배열로 구현
- append(), insert(), pop(), remove() 등의 다양한 메서드 제공
- 인덱스를 통해 빠르게 접근 가능
- 스택 (Stack)
- LIFO(Last In First Out): 나중에 들어온 데이터가 먼저 나감
- Push: 데이터를 스택에 추가
- Pop: 스택에서 데이터를 제거
- 큐 (Queue)
- FIFO(First In First Out): 먼저 들어온 데이터가 먼저 나감 -> 스택과 반대
- Enqueue(인큐): 큐의 뒤쪽(rear)에 데이터 삽입
- Dequeue(디큐): 큐의 앞쪽(front)에 데이터 제거
from collections import deque
queue_ex = deque()
queue_ex.append(10) # enqueue
queue_ex.append(20)
queue_ex.append(30)
print(queue_ex) # deque([10, 20, 30])
queue_ex.popleft() # dequeue → 10 제거
queue_ex.popleft() # dequeue → 20 제거
print(queue_ex) # deque([30])#Python 클래스 구현
class Queue:
def __init__ (self):
self.items = [] #큐 저장 공간 (리스트)
self.front_index = 0 #다음에 dequeue될 원소 위치
def enqueue(self, value):
self.items.append(value) #큐의 뒤에 값 추가
def dequeue(self):
if self.front_index == len(self.items): #큐가 비었는지 확인
print("Queue is empty")
return None
else:
x = self.items[self.front_index] #맨 앞의 값
self.front_index += 1 #포인터 한 칸 이동
#front_index만 이동하므로, 실제 리스트는 계속 쌓임 (메모리 낭비 발생 가능)
return x- ❓배열 vs 연결 리스트
- 배열: 연속된 메모리 공간, 인덱스 접근 빠름(O(1)), 고정된 크기
- 연결 리스트: 노드들이 포인터로 연결, 삽입/삭제 유리, 접근 느림(O(n))
- ❓데크(Deque: Double-Ended Queue)
- 스택과 큐의 기능을 모두 포함
- 양쪽 끝에서 삽입과 삭제 모두 가능
- from collection import deque → deque를 사용하기 위해 모듈에서 불러옴
- 데크의 연산
- appendleft(): 왼쪽 끝에 삽입
- append(): 오른쪽 끝에 삽입
- popleft(): 왼쪽 끝에서 삭제
- pop(): 오른쪽 끝에서 삭제
7. 비선형 자료구조
📌트리, 그래프
- 이진 트리 (Binary Tree)
- 각 노드가 자식을 없거나, 1개 또는 최대 2개 까지만 가질 수 있는 트리
- 1) 구성 요소
- 노드: 트리의 각 구성 요소
- 링크 또는 엣지: 노드들을 연결하는 선
- 루프 노드: 맨 위에 있는 최고 조상 노드
- 리프 노드: 자식이 없는 노드
- 2) 표현 방법
- 리스트로 표현
- 간단하지만 빈 공간이 많을 수 있음
- 레벨 0부터 시작하여 -> 각 레벨에서 왼쪽부터 오른쪽으로 -> 없는 노드는 None(널)로 표시
- 재귀적으로 표현 (중첩 리스트)
- 트리의 구조를 잘 나타냄
- [노드값, 왼쪽 서브트리, 오른쪽 서브트리]
- 노드 클래스로 직접 표현
- 가장 직관적이고 유연
- key, left, right, parent, value로 구성되어 있다
- 리스트로 표현
- 그래프 (Graph)
- 1) 개념 및 구성요소
- 가장 일반적이고 복잡한 자료 구조
- G = (V, E) 로 표현
- V: 정점(Vertex) 집합
- E: 엣지(Edge) 집합
- 정점 또는 노드: 동그라미로 표현되는 각 점
- 엣지 또는 링크: 노드들을 연결하는 선
- 2) 종류
- 무방향 그래프: 엣지에 방향성이 없음 ➡️ 양방향 이동 가능
- 방향 그래프: 엣지에 방향성이 있음 ➡️ 화살표로 표시
- 가중치 그래프: 각 엣지에 가중치 값이 있음 ➡️ 비용, 거리, 시간 등 나타낼 수 있음
- A - B 간선의 가중치가 5이면, A에서 B까지의 거리/비용이 5라는 의미
- 3) 표현 방법
- 인접 행렬
- 2차원 배열로 간선 여부 표시
- 구현은 단순하나 노드 수가 많으면 메모리를 많이 사용한다는 의미
- 예) matrix[i][j] = 1 # i번 노드와 j번 노드 사이에 엣지 존재
matrix[i][j] = 0 # 엣지 없음
- 인접 리스트
- 각 정점이 연결된 정점들을 리스트로 저장
- 메모리를 효율적으로 사용한다
- 인접 행렬
- 1) 개념 및 구성요소
'부트캠프 정리' 카테고리의 다른 글
| [멋쟁이사자처럼 데이터분석 부트캠프 6주차]-통계 기법 (17) | 2025.08.08 |
|---|---|
| [멋쟁이사자처럼 데이터분석 부트캠프 5주차]-데이터전처리기초 (6) | 2025.07.31 |
| [멋쟁이사자처럼부트캠프 데이터분석 2주차]-파이썬 모듈/데이터분석 기초 (8) | 2025.07.25 |
| [멋쟁이사자처럼 데이터분석 부트캠프 1주차]-파이썬 기초 (16) | 2025.07.24 |
| [멋쟁이사자처럼 데이터분석 부트캠프 4주차]-SQL (2) | 2025.07.22 |