스택(Stack)
- 후입선출(Last In First Out) 구조
- 마지막에 들어온 데이터가 가장 먼저 나간다
- 파이썬에서는 리스트와 pop(), append() 메소드로 스택을 구현할 수 있다
큐(Queue)
- 선입선출(First In First Out) 구조
- 먼저 들어온 데이터가 가장 먼저 나간다. “공정한 자료구조”
- from collections import deque 사용해서 deque 자료구조를 활용하는 게 좋다
- deque는 스택, 큐의 장점을 모두 채택한 것인데 리스트에 비해 빠르고 queue 라이브러리를 이용하는 것 보다 간단하다
- append(), popleft()를 이용하여 큐를 구현할 수 있다
DFS(Depth-First Search, 깊이 우선 탐색)
- 그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘
- 스택 자료구조를 이용하며, visited(방문 처리)를 이용해서, 스택에 한번 삽입되어 처리된 노드가 다시 삽입되지 않게 한다. 방문 처리를 통해 각 노드를 한번씩만 처리한다.
- 일반적으로 방문하지 않은 노드 중에서, 번호가 낮은 순서부터 처리한다. ( DFS 기능 상 순서와 상관없이 처리해도 되지만, 관행적으로 그렇다 )
- 재귀 함수를 이용하면 구현이 간단하다.
- O(N)의 시간 복잡도를 가진다.
Graph(그래프)의 기본 구조
- 그래프는 노드(Node)와 간선(Edge)으로 표현된다. 노드는 정점(Vertex)이라고도 한다
- 두 노드가 간선으로 연결되어 있다면, 두 노드는 인접하다(Adjacent)라고 표현한다
- 노드와 간선으로 이루어진다.
- 0과 1간의 이동은 비용7, 0와 2간의 이동은 비용5가 든다.
- 간선으로 연결되지 않은 노드간의 비용은 “무한”으로 표기한다.
- “무한”은 999999999나 987654321같은 논리적으로 정답이 될 수 없는 값 중에서 초기화하는 경우가 많다.
그래프를 표현하는 두 가지 방식
인접 행렬(Adjacency Matrix)
- 2차원 배열로 그래프 연결 관계 표현
- 위 그림의 오른쪽 표처럼 인접 행렬은 2차원 배열 형태로 구현하게 된다.
인접 리스트(Adjacency List)
- 리스트로 그래프 연결 관계 표현
- 인접 리스트는 "연결 리스트" 라는 자료구조를 이용해 구현한다.
- 파이썬은 리스트 자료형이 연결 리스트 기능을 제공한다.
- 인접 행렬과 비슷하게 2차원 배열 형태로 저장한다.
- graph = [[(1, 7), (2, 5)], [(0, 7)], [(0, 5)] -> 인접 행렬과 다르게 연결되지 않은 곳은 저장하지 않는다!!
- graph[i]는 출발지를 의미하며, (목적지, 거리) 식으로 저장된다.
- 저장되지 않았다면 간선으로 연결되지 않은 것이다.
인접 행렬과 인접 리스트의 장단점
- 메모리 측면에서, 인접 행렬은 모든 관계를 저장하므로 노드 개수가 많을수록 메모리가 낭비된다. 반면 인접 리스트는 연결된 정보만을 저장하기 때문에 메모리를 효율적으로 사용한다.
- 하지만 인접 리스트는 인접 행렬 방식에 비해, 두 노드가 연결되어 있는지 확인하는 속도가 느리다.
- 만약 “모든 인접 노드를 순회”해야 하는 경우, 인접 리스트 방식이 더 효율적이다.
DFS 탐색 과정
- 시작 노드를 스택에 삽입하고 방문 처리 (삽입하면 최상단에 위치한다)
- 스택의 최상단 노드의 방문하지 않은 인접 노드 중, 가장 작은 노드를 스택에 넣고 방문 처리를 반복한다.
- 방문하지 않은 인접 노드가 없다면, 해당 노드를 스택에서 꺼낸 후 돌아간다.
- 방문하지 않은 인접 노드가 있는 노드로 돌아갈 때까지 노드를 스택에서 꺼낸다.
- 모든 노드에 방문 처리가 될 때까지 진행한다.
- 한번 스택에 들어갔다면 반드시 방문 처리를 해야 한다.
아래는 DFS 예제 코드이다.
연결된 모든 노드를 한번 씩 방문하고 방문할 때마다 방문했다는 문구를 출력한다.
이 코드를 이해하고 DFS, 백트래킹 문제를 푸니 훨씬 수월했다.
백트래킹(backtracking)
- DFS처럼 모든 경우의 수를 탐색하되, 조건을 걸어서 유망하지 않을 경우(더이상 탐색해도 의미가 없을 경우) 가지치기를 하고 이전 노드로 되돌아가 다른 경우의 수를 탐색한다.
- 불필요한 부분을 쳐내는 걸 가지치기 라고 한다. ( 불필요한 부분 : 더이상 탐색해도 답이 되지 않을 경우의 수 )
이분 탐색(Binary Search)
- 정렬되어 있는 리스트에서 탐색 범위를 절반씩 좁혀가며 데이터를 탐색하는 방법
- 시간 복잡도는 O(logN)으로 빠른 편이다.
- 특정 배열에 특정 데이터가 있는지 조사할 때, 이분 탐색을 사용하면 굉장히 효율적이다.
- 일반적으로 start, end, mid 값을 이용해 구현한다. start는 탐색 시작지점, end는 탐색 끝 지점, mid는 start와 end의 중간지점이다.
- 찾을 데이터가 mid보다 위에 있다면 start를 올리고, mid보다 아래에 있다면 end를 내려가며 진행한다.
- 배열에서 특정 데이터를 찾기 원할 때 이 함수를 이용하기만 하면 된다.
'크래프톤 정글 > TIL' 카테고리의 다른 글
[크래프톤 정글 5기] week02 알고리즘 주차 아홉번째 날, 분할 정복, 뮤터블, 그래프, 트리, DFS/BFS, 이진검색트리, 서로소집합 (2) | 2024.03.29 |
---|---|
[크래프톤 정글 5기] week01 알고리즘 주차 여섯번째 날, 해시 테이블, 힙, 우선순위 큐, 이진 트리, 피보나치 (0) | 2024.03.26 |
[크래프톤 정글 5기] week01 알고리즘 주차 다섯번째 날, CPU, 인스트럭션, 퀵 정렬(Quick Sort) (0) | 2024.03.26 |
[크래프톤 정글 5기] week01 알고리즘 주차 두번째 날, Big-O, 시간/공간 복잡도 (2) | 2024.03.23 |
[크래프톤 정글 5기] 첫 미니 프로젝트[타잔]을 진행하며 배운 것 feat.JWT, jinja2 (0) | 2024.03.21 |