데이터 구조, 한재엽님의 Part 1-2 Data Structure를 기반으로 여러분들의 블로그를 참조!
02. DataStructure
Array vs LinkedList
Array
- 논리적 저장 순서 = 물리적 저장 순서
- 접근하고자 하는 값의 인덱스를 알고 있다면, 상수 시간(Big-O(1))에 접근할 수 있다.
- Random access가 가능하다
- 하지만 삭제, 삽입 과정에서 엄청난 시간이 걸린다(논리적 저장 순서 = 물리적 저장 순서 때문에..)
LinkedList
- 자기 자신 다음의 원소가 누군지만 알고있음, 삭제와 삽입이 상수 시간에 가능
- 특정 값을 사용하기 위해서는 O(n) 시간 필요(처음부터 물고물고 찾아가야함)
- 결국 삭제, 삽입 시에도 특정 값을 찾아야하므로 O(n)시간이 걸림..
Stack and Queue
Stack
- LIFO
Queue
- FIFO
Tree
비선형자료구조, 계층적 관계를 표현(Hierarchical Relationship)
- node: 트리를 구성하는 각각 요소
- edge: 노드와 노드를 연결하는 선
- root node: 트리 구조의 최상단에 있는 노드
- terminal node(leaf node): 하위에 아무 노드도 없는 노드
- internal node: 단말 노드(terminal node)를 제외한 모든 노드, 루트 노드 포함
Binary tree
- 루트 노드를 중심으로 두 개의 서브 트리로 구성
- 서브 트리도 binary tree
- root node의 level : 0
- height : 트리의 최고 레벨
- Full Binary Tree (포화 이진 트리) / Complete Binary Tree (완전 이진 트리)
- 포화 이진 트리 : 모든 레벨이 꽉찬 이진 트리
- 완전 이진 트리 : 위->아래, 왼쪽->오른쪽 순서로 차곡차곡 채워진 트리
- parent(i) = i/2
- left_child(i) = 2i,
- right_child(i) = 2i+1
BST(Binary Search Tree)
효율적인 탐색을 위한 저장
- 규칙1. 이진탐색 트리의 노드에 저장된 키는 유일함
- 규칙2. 루트 노드의 키가 왼쪽 서브 트리를 구성하는 어떤 노드의 키보다 크다.
- 규칙3. 루트 노드의 키가 오른쪽 서브 트리를 구성하는 어떤 노드의 키보다 작다.
- 규칙4. 왼쪽과 오른쪽의 서브트리 역시 이진 탐색 트리. 트리가 한 쪽으로 편향되어 구성될 경우 의미가 없어지므로 균형을 잡기위해 rebalancing(Red-Black Tree 등과 같은)을 한다.
Binary Heap
- Complete Binary Tree
- 0번을 건너뛰고 1번 index부터 루트노드가 시작
- 루트노드 제거 시, 맨 마지막 노드를 root node에 놓고 heapify
- heapify
- O(log n) : 최대 root node부터 맨 아래 까지 내려가며 교체가 일어날 수 있으므로
- heapify
- max heap / min heap
- max heap
- 각 노드의 값이 노드의 children보다 크거나 같은 complete binary tree
- max : root node
- min heap
- 각 노드의 값이 노드의 children보다 작거나 같은 complete binary tree
- max heap
Red Black Tree
BST 기반의 트리형식 자료구조, Search, Insert, Delete에 O(log n)의 시간 복잡도 소요
- 각 노드는 Red or Black의 색깔을 가짐
- Root node : black
- leaf node : black
- 어떤 노드의 색깔이 red이면, children은 black
- 노드 ~ descendant leaves까지의 단순경로는 같은 수의 black nodes를 포함 : Black-Height
HashTable
- 내부적으로 배열을 사용하여 특정값을 찾는데에 상수시간에 접근이 가능
- 특별한 알고리즘을 이용하여 저장데이터와 연관이 되는 고유한 숫자를 인덱스로 사용
hash function
- Collision을 최소화하는 방향으로 설계되어야함
- 1:1대응에 가갑게 만드는것은 거의불가능 / array와 다를바 없음
Collision 해결방법
- Open Address방식(개방주소법)
- 해시 충돌 발생시, 다른 해시 버킷에 자료를 삽입
- Linear Probing : 순차적으로 빈 버킷 탐색
- Quadratic probing : 2차 함수를 이용하여 탐색
- Double hashing probing : 충돌발생시 2차 해쉬 함수를 이용하여 새주소 할당(연산량 가중)
- Seperate Chaining방식(분리연결법)
- Open Address방식에 비해 빠름
- Open Address방식의 경우 해시 버킷 밀도가 높아지면 재 탐색 비율이 높아짐
- Linked List : 각각의 버킷들을 연결리스트로 만들어 충돌 발생시 list삽입
- Red-Black Tree : 연결 리스트 대신 트리를 사용, 다만 메모리 측면에서 데이터의 갯수가 작으면 Linked List사용
- 데이터가 작다는 것의 의미
- 하나의 해시 버킷에 할당된 key-value 쌍의 갯수 기준
- 6-8개 기준, 기준이 7이면 6되었다가 7이 될 때마다 구조변경이 발생하므로 약간의 버퍼를 둠.
해시 버킷 동적 확장(Resize)
-
해시 버킷의 개수가 적으면 메모리의 절약이 가능하지만 해시충돌로 인한 성능 손실이 발생, 따라서 HashMap의 key-value 쌍이 일정 개수 이상(해시 버켓의 0.75, load factor)이 되면, 해시 버킷의 개수를 두 배로 늘림.
Graph
graph : 정점과 간선의 집합
- 트리, 싸이클이 허용되지 않는 그래프
그래프 관련 용어
- Undirected Graph / Directed Graph(Digraph)
- 정점과 간선 간 방향성 유무에 따라 구분
- Undirected Graph
- Degree
- Undirected Graph에서 각 정점(vertex)에 연결된 Edge의 개수를 Degree라 함.
- Directed graph에서는 간선의 방향이 존재하므로 Degree가 2개로 나뉨, 정점으로 나가는 **간선의 수를 **outdegree, 들어오는 간선의 수를 indegree라 함.
- 가중치 그래프(Weight Graph)
- 간선에 가중치 정보를 두어 구성한 그래프
- 부분 그래프(Sub Graph)
- 부분 집합과 유사한 개념의 부분 그래프
그래프 구현 방법
- 인접 행렬(adjacent matrix) : 정방 행렬을 사용
- 해당 위치의 value값을 이용하여 연결관계를 상수시간에 파악할 수 있다.
- V^2의 space complexity를 가진다.
- Dense graph에 적절(edge의 수가 최대 간선의 수에 가까운 그래프)
- 인접 리스트(adjacent list) : 연결 리스트를 사용
- 확인코자 하는 vertax의 adjacent list를 확인해야 하므로 시간이 오래 걸림
- Space Complexity : O(E+V)
- Sparse graph에 적절
그래프 탐색
그래프는 정점의 구성과 연결규칙이 존재하지 않아 탐색이 복잡하다.
- 깊이 우선 탐색(Depth First Search:DFS)
- 연결할 수 있는 정점을 끝까지 쫒아간다, 더이상 연결된 정점이 없으면 바로 직전으로 돌아가며 반복한다.
- Stack을 이용해 구현한다.
- Time Complexity : O(V+E) … vertex 개수 + edge 개수
- 너비 우선 탐색(Breadth First Search:BFS)
- 한 정점에 연결된 모든 정점들로 나아감
- Queue를 이용
- 탐색을 시작하는 정점을 Queue에 넣고, dequeue하며, 각 정점과 간선으로 연결된 정점들을 enqueue 반복
- Time Complexity : O(V+E) … vertext 개수 + edge 개수
Minimum Spanning Tree
그래프의 spanning tree(그래프의 모든 vertex가 cycle없이 연결) 중 edge weight 합이 최소인 것.
- Kruskal Algorithm
- weight가 가장 작은 간선부터 검토
- cycle형성 하지 않는 경우에만 간선 추가
- spanning tree 완성 시까지 or 모든 간선 검토 시까지(spanning tree 불가 시)
- cycle 생성 여부 판단?
- 연결된 vertex들에 동일한 group-id 할당,
- 연결하고자 하는 두 vertex의 group-id가 동일하면 cycle!!
- 시간복잡도
- O(ElogE)
- Prim Algorithm
- 그래프에서 하나의 꼭짓점을 선택하여 트리 생성
- 그래프의 모든 변이 들어있는 집합 생성
- 트리가 모든 꼭지점을 포함할 때 까지
- 트리가 포함하는 꼭지점끼리의 연결이 아닌, 가중치가 가장 작은 변이 연결하는 변을 그래프에 추가
- 시간복잡도
- O(ElogV)