-- INDEX --
1. Array | 2. Linked List | 3. Stack | 4. Queue |
인덱스로 해당 원소 접근 가능 |
자기 자신 다음만을 기억 | LIFO FILO |
FIFO interface Queue |
5. Tree | 6. Binary Heap | 7. Red Black Tree | 8. Graph |
비선형 자료구조 표현에 집중 BinaryTree BST |
배열에 기반한 Complete Binary Tree MaxHip / MinHip |
BST를 기반한 트리 형식의 자료구조 depth 최소화하여 시간복잡도 줄이는 것 |
정점과 간선의 집합 DFS 와 BFS |
1. Array
- 가장 기본적인 자료구조인 Array 자료구조는, 논리적 저장 순서와 물리적 저장 순서가 일치한다.
- 따라서 인덱스(index)로 해당 원소(element)에 접근할 수 있다.
- 그렇기 때문에 찾고자 하는 원소의 인덱스 값을 알고 있으면 Big-O(1)에 해당 원소로 접근할 수 있다.
- 즉 random access 가 가능하다는 장점이 있는 것이다.
- 하지만 삭제 또는 삽입의 과정에서는 해당 원소에 접근하여 작업을 완료한 뒤(O(1)), 또 한 가지의 작업을 추가적으로 해줘야 하기 때문에, 시간이 더 걸린다.
- 만약 배열의 원소 중 어느 원소를 삭제했다고 했을 때, 배열의 연속적인 특징이 깨지게 된다. 즉 빈 공간이 생기는 것이다.
- 따라서 삭제한 원소보다 큰 인덱스를 갖는 원소들을 shift 해줘야 하는 비용(cost)이 발생하고 이 경우의 시간 복잡도는 O(n)가 된다.
- 그렇기 때문에 Array 자료구조에서 삭제 기능에 대한 time complexity 의 worst case 는 O(n)이 된다.
- 삽입의 경우도 마찬가지이다. 만약 첫번째 자리에 새로운 원소를 추가하고자 한다면 모든 원소들의 인덱스를 1 씩 shift 해줘야 하므로 이 경우도 O(n)의 시간을 요구하게 된다.
2. Linked List
- 이 부분(삭제 또는 삽입 과정에서의 추가 작업)에 대한 문제점을 해결하기 위한 자료구조가 linked list 이다.
- 각각의 원소들은 자기 자신 다음에 어떤 원소인지만을 기억하고 있다.
- 따라서 이 부분만 다른 값으로 바꿔주면 삭제와 삽입을 O(1) 만에 해결할 수 있는 것이다.
- 하지만 Linked List 역시 한 가지 문제가 있다.
- 원하는 위치에 삽입을 하고자 하면 원하는 위치를 Search 과정에 있어서 첫 번째 원소부터 다 확인해봐야 한다는 것이다.
- Array 와는 달리 논리적 저장 순서와 물리적 저장 순서가 일치하지 않기 때문이다.
- 이것은 일단 삽입하고 정렬하는 것과 마찬가지이다.
- 이 과정 때문에, 어떠한 원소를 삭제 또는 추가하고자 했을 때, 그 원소를 찾기 위해서 O(n)의 시간이 추가적으로 발생하게 된다.
- 결국 linked list 자료구조는 search 에도 O(n)의 time complexity 를 갖고, 삽입, 삭제에 대해서도 O(n)의 time complexity 를 갖는다.
- 그렇다고 해서 아주 쓸모없는 자료구조는 아니기에, 우리가 학습하는 것이다.
- 이 Linked List 는 Tree 구조의 근간이 되는 자료구조이며, Tree 에서 사용되었을 때 그 유용성이 드러난다.
3. Stack
- 선형 자료구조의 일종으로 Last In First Out (LIFO) - 나중에 들어간 원소가 먼저 나온다.
- 또는 First In Last Out (FILO) - 먼저 들어간 원소가 나중에 나온다. 이것은 Stack 의 가장 큰 특징이다.
- 차곡차곡 쌓이는 구조로 먼저 Stack 에 들어가게 된 원소는 맨바닥에 깔리게 된다.
- 그렇기 때문에 늦게 들어간 녀석들은 그 위에 쌓이게 되고 호출 시 가장 위에 있는 녀석이 호출되는 구조이다.
4. Queue
- 선형 자료구조의 일종으로 First In First Out (FIFO). 즉, 먼저 들어간 놈이 먼저 나온다.
- Stack 과는 반대로 먼저 들어간 놈이 맨 앞에서 대기하고 있다가 먼저 나오게 되는 구조이다.
- 참고로 Java Collection 에서 Queue 는 인터페이스이다. 이를 구현하고 있는 Priority queue등을 사용할 수 있다.
5. Tree
- 트리는 스택이나 큐와 같은 선형 구조가 아닌 비선형 자료구조이다.
- 트리는 계층적 관계(Hierarchical Relationship)을 표현하는 자료구조이다.
- 이 트리라는 자료구조는 표현에 집중한다.
- 무엇인가를 저장하고 꺼내야 한다는 사고에서 벗어나 트리라는 자료구조를 바라보자.
5-1 : 트리를 구성하고 있는 구성요소들(용어)
- Node (노드) : 트리를 구성하고 있는 각각의 요소를 의미한다.
- Edge (간선) : 트리를 구성하기 위해 노드와 노드를 연결하는 선을 의미한다.
- Root Node (루트 노드) : 트리 구조에서 최상위에 있는 노드를 의미한다.
- Terminal Node ( = leaf Node, 단말 노드) : 하위에 다른 노드가 연결되어 있지 않은 노드를 의미한다.
- Internal Node (내부노드, 비단말 노드) : 단말 노드를 제외한 모든 노드로 루트 노드를 포함한다.
5-2 : Binary Tree ( 이진 트리 )
- 루트 노드를 중심으로 두 개의 서브 트리(큰 트리에 속하는 작은 트리)로 나누어진다.
- 또한 나뉘어진 두 서브 트리도 모두 이진 트리어야 한다. 재귀적인 정의라 맞는듯 하면서도 이해가 쉽지 않을 듯하다.
- 한 가지 덧붙이자면 공집합도 이진 트리로 포함시켜야 한다.
- 그래야 재귀적으로 조건을 확인해 갔을 때, leaf node 에 다다랐을 때, 정의가 만족되기 때문이다.
- 자연스럽게 노드가 하나뿐인 것도 이진 트리 정의에 만족하게 된다.
- 트리에서는 각 층별로 숫자를 매겨서 이를 트리의 Level(레벨)이라고 한다.
- 레벨의 값은 0 부터 시작하고 따라서 루트 노드의 레벨은 0 이다.
- 그리고 트리의 최고 레벨을 가리켜 해당 트리의 height(높이)라고 한다.
5-3 : Perfect Binary Tree (포화 이진 트리), Complete Binary Tree (완전 이진 트리), Full Binary Tree (정 이진 트리)
- 모든 레벨이 꽉 찬 이진 트리를 가리켜 포화 이진 트리라고 한다.
- 위에서 아래로, 왼쪽에서 오른쪽으로 순서대로 차곡차곡 채워진 이진 트리를 가리켜 완전 이진 트리라고 한다.
- 모든 노드가 0개 혹은 2개의 자식 노드만을 갖는 이진 트리를 가리켜 정 이진 트리라고 한다.
- 배열로 구성된 Binary Tree는 노드의 개수가 n 개이고 root가 0이 아닌 1에서 시작할 때,
- i 번째 노드에 대해서 parent(i) = i/2 , left_child(i) = 2i , right_child(i) = 2i + 1 의 index 값을 갖는다.
5-4 : BST (Binary Search Tree)
- 효율적인 탐색을 위해서는 어떻게 찾을까만 고민해서는 안된다.
- 그보다는 효율적인 탐색을 위한 저장방법이 무엇일까를 고민해야 한다.
- 이진 탐색 트리는 이진 트리의 일종이다.
- 단 이진 탐색 트리에는 데이터를 저장하는 규칙이 있다.
- 그리고 그 규칙은 특정 데이터의 위치를 찾는 데 사용할 수 있다.
- 규칙 1. 이진 탐색 트리의 노드에 저장된 키는 유일하다.
- 규칙 2. 부모의 키가 왼쪽 자식 노드의 키보다 크다.
- 규칙 3. 부모의 키가 오른쪽 자식 노드의 키보다 작다.
- 규칙 4. 왼쪽과 오른쪽 서브트리도 이진 탐색 트리이다.
- 이진 탐색 트리의 탐색 연산은 O(log n)의 시간 복잡도를 갖는다. 사실 정확히 말하면 O(h)라고 표현하는 것이 맞다.
- 트리의 높이를 하나씩 더해갈수록 추가할 수 있는 노드의 수가 두 배씩 증가하기 때문이다.
- 하지만 이러한 이진 탐색 트리는 Skewed Tree(편향 트리)가 될 수 있다.
- 저장 순서에 따라 계속 한쪽으로만 노드가 추가되는 경우가 발생하기 때문이다.
- 이럴 경우 성능에 영향을 미치게 되며, 탐색의 Worst Case 가 되고 시간 복잡도는 O(n)이 된다.
- 배열보다 많은 메모리를 사용하며 데이터를 저장했지만 탐색에 필요한 시간 복잡도가 같게 되는 비효율적인 상황이 발생한다.
- 이를 해결하기 위해 Rebalancing 기법이 등장하였다. 균형을 잡기 위한 트리 구조의 재조정을 Rebalancing이라 한다.
- 이 기법을 구현한 트리에는 여러 종류가 존재하는데 그중에서 하나가 뒤에서 살펴볼 Red-Black Tree이다.
6. Binary Heap
- 자료구조의 일종으로 Tree 의 형식을 하고 있으며, Tree 중에서도 배열에 기반한 Complete Binary Tree이다.
- 배열에 트리의 값들을 넣어줄 때, 0 번째는 건너뛰고 1 번 index 부터 루트노드가 시작된다.
- 이는 노드의 고유번호 값과 배열의 index 를 일치시켜 혼동을 줄이기 위함이다.
- 힙(Heap)에는 최대힙(max heap), 최소힙(min heap) 두 종류가 있다.
- Max Heap이란, 각 노드의 값이 해당 children 의 값보다 크거나 같은 complete binary tree를 말한다. ( Min Heap 은 그 반대이다.)
- Max Heap에서는 Root node 에 있는 값이 제일 크므로, 최대값을 찾는데 소요되는 연산의 time complexity 이 O(1)이다. 그리고 complete binary tree이기 때문에 배열을 사용하여 효율적으로 관리할 수 있다. (즉, random access 가 가능하다.
- Min heap 에서는 최소값을 찾는데 소요되는 연산의 time complexity 가 O(1)이다.) 하지만 heap 의 구조를 계속 유지하기 위해서는 제거된 루트 노드를 대체할 다른 노드가 필요하다. 여기서 heap 은 맨 마지막 노드를 루트 노드로 대체시킨 후, 다시 heapify 과정을 거쳐 heap 구조를 유지한다. 이런 경우에는 결국 O(log n)의 시간복잡도로 최대값 또는 최소값에 접근할 수 있게 된다.
7. Red Black Tree
- RBT(Red-Black Tree)는 BST 를 기반으로 하는 트리 형식의 자료구조이다.
- 결론부터 말하자면 Red-Black Tree 에 데이터를 저장하게 되면 Search, Insert, Delete 에 O(log n)의 시간 복잡도가 소요된다.
- 동일한 노드의 개수일 때, depth 를 최소화하여 시간 복잡도를 줄이는 것이 핵심 아이디어이다.
- 동일한 노드의 개수일 때, depth 가 최소가 되는 경우는 tree 가 complete binary tree 인 경우이다.
7-1 : Red-Black Tree 의 정의
- Red-Black Tree 는 다음의 성질들을 만족하는 BST 이다.
- 각 노드는 Red or Black이라는 색깔을 갖는다.
- Root node 의 색깔은 Black이다.
- 각 leaf node 는 black이다.
- 어떤 노드의 색깔이 red라면 두 개의 children 의 색깔은 모두 black 이다.
- 각 노드에 대해서 노드로부터 descendant leaves 까지의 단순 경로는 모두 같은 수의 black nodes 들을 포함하고 있다. 이를 해당 노드의 Black-Height라고 한다.
- cf) Black-Height: 노드 x 로부터 노드 x 를 포함하지 않은 leaf node 까지의 simple path 상에 있는 black nodes 들의 개수
7-2 : Red-Black Tree 의 특징
- Binary Search Tree 이므로 BST 의 특징을 모두 갖는다.
- Root node 부터 leaf node 까지의 모든 경로 중 최소 경로와 최대 경로의 크기 비율은 2 보다 크지 않다. 이러한 상태를 balanced 상태라고 한다.
- 노드의 child 가 없을 경우 child 를 가리키는 포인터는 NIL 값을 저장한다. 이러한 NIL 들을 leaf node 로 간주한다.
- RBT 는 BST 의 삽입, 삭제 연산 과정에서 발생할 수 있는 문제점을 해결하기 위해 만들어진 자료구조이다. 이를 어떻게 해결한 것인가?
7-3 : 삽입
- 우선 BST 의 특성을 유지하면서 노드를 삽입을 한다.
- 그리고 삽입된 노드의 색깔을 RED 로 지정한다.
- Red 로 지정하는 이유는 Black-Height 변경을 최소화하기 위함이다.
- 삽입 결과 RBT 의 특성 위배(violation)시 노드의 색깔을 조정하고, Black-Height 가 위배되었다면 rotation 을 통해 height 를 조정한다.
- 이러한 과정을 통해 RBT 의 동일한 height 에 존재하는 internal node 들의 Black-height 가 같아지게 되고 최소 경로와 최대 경로의 크기 비율이 2 미만으로 유지된다.
7-4 : 삭제
- 삭제도 삽입과 마찬가지로 BST 의 특성을 유지하면서 해당 노드를 삭제한다.
- 삭제될 노드의 child 의 개수에 따라 rotation 방법이 달라지게 된다.
- 그리고 만약 지워진 노드의 색깔이 Black 이라면 Black-Height 가 1 감소한 경로에 black node 가 1 개 추가되도록 rotation 하고 노드의 색깔을 조정한다.
- 지워진 노드의 색깔이 red 라면 Violation 이 발생하지 않으므로 RBT 가 그대로 유지된다.
- Java Collection 에서 TreeMap 도 내부적으로 RBT 로 이루어져 있고, HashMap 에서의 Separate Chaining에서도 사용된다. 그만큼 효율이 좋고 중요한 자료구조이다.
8. Graph
- 정점과 간선의 집합, Graph
- cf) 트리 또한 그래프이며, 그 중 사이클이 허용되지 않는 그래프를 말한다.
8-1 : 그래프 관련 용어 정리
8-1-1 : Undirected Graph 와 Directed Graph (Digraph)
- 말 그대로 정점과 간선의 연결관계에 있어서 방향성이 없는 그래프를 Undirected Graph 라 하고,
- 간선에 방향성이 포함되어 있는 그래프를 Directed Graph 라고 한다.
- Directed Graph (Digraph)
V = {1, 2, 3, 4, 5, 6}
E = {(1, 4), (2,1), (3, 4), (3, 4), (5, 6)}
(u, v) = vertex u에서 vertex v로 가는 edge
- Undirected Graph
V = {1, 2, 3, 4, 5, 6}
E = {(1, 4), (2,1), (3, 4), (3, 4), (5, 6)}
(u, v) = vertex u와 vertex v를 연결하는 edge
8-1-2 : Degree
- Undirected Graph 에서 각 정점(Vertex)에 연결된 Edge 의 개수를 Degree 라 한다.
- Directed Graph 에서는 간선에 방향성이 존재하기 때문에 Degree 가 두 개로 나뉘게 된다.
- 각 정점으로부터 나가는 간선의 개수를 Outdegree 라 하고, 들어오는 간선의 개수를 Indegree 라 한다.
8-1-3 : 가중치 그래프(Weight Graph)와 부분 그래프(Sub Graph)
- 가중치 그래프란 간선에 가중치 정보를 두어서 구성한 그래프를 말한다.
- 반대의 개념인 비가중치 그래프 즉, 모든 간선의 가중치가 동일한 그래프도 물론 존재한다.
- 부분 집합과 유사한 개념으로 부분 그래프라는 것이 있다.
- 부분 그래프는 본래의 그래프의 일부 정점 및 간선으로 이루어진 그래프를 말한다.
8-2 : 그래프를 구현하는 두 방법
8-2-1 : 인접 행렬 (adjacent matrix) : 정방 행렬을 사용하는 방법
- 해당하는 위치의 value 값을 통해서 vertex 간의 연결 관계를 O(1) 으로 파악할 수 있다.
- Edge 개수와는 무관하게 V^2 의 Space Complexity 를 갖는다.
- Dense graph 를 표현할 때 적절할 방법이다.
8-2-2 : 인접 리스트 (adjacent list) : 연결 리스트를 사용하는 방법
- vertex 의 adjacent list 를 확인해봐야 하므로 vertex 간 연결되어 있는지 확인하는데 오래 걸린다.
- Space Complexity 는 O(E + V)이다. Sparse graph 를 표현하는데 적당한 방법이다.
8-3 : 그래프 탐색
- 그래프는 정점의 구성뿐만 아니라 간선의 연결에도 규칙이 존재하지 않기 때문에 탐색이 복잡하다.
- 따라서 그래프의 모든 정점을 탐색하기 위한 방법은 다음의 두 가지 알고리즘을 기반으로 한다.
8-3-1 : 깊이 우선 탐색 (Depth First Search: DFS)
- 그래프 상에 존재하는 임의의 한 정점으로부터 연결되어 있는 한 정점으로만 나아간다라는 방법을 우선으로 탐색한다.
- 일단 연결된 정점으로 탐색하는 것이다. 연결할 수 있는 정점이 있을 때까지 계속 연결하다가 더 이상 연결될 수 있는 정점이 없으면 바로 그 전 단계의 정점으로 돌아가서 연결할 수 있는 정점이 있는지 살펴봐야 할 것이다.
- 갔던 길을 되돌아오는 상황이 존재하는 미로 찾기처럼 구성하면 되는 것이다.
- 어떤 자료구조를 사용해야 할까? 바로 Stack 이다.
- Time Complexity : O(V+E) … vertex 개수 + edge 개수
8-3-2 : 너비 우선 탐색 (Breadth First Search: BFS)
- 그래프 상에 존재하는 임의의 한 정점으로부터 연결되어 있는 모든 정점으로 나아간다.
- Tree 에서의 Level Order Traversal 형식으로 진행되는 것이다.
- BFS 에서는 자료구조로 Queue 를 사용한다. 연락을 취할 정점의 순서를 기록하기 위한 것이다.
- 우선, 탐색을 시작하는 정점을 Queue 에 넣는다.(enqueue) 그리고 dequeue 를 하면서 dequeue 하는 정점과 간선으로 연결되어 있는 정점들을 enqueue 한다.
- 즉 vertex 들을 방문한 순서대로 queue 에 저장하는 방법을 사용하는 것이다.
- Time Complexity : O(V+E) … vertex 개수 + edge 개수
- ! 모든 간선에 가중치가 존재하지 않거나 모든 간선의 가중치가 같은 경우, BFS 로 구한 경로는 최단 경로이다.
# 참고자료
https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/DataStructure
GitHub - JaeYeopHan/Interview_Question_for_Beginner: Technical-Interview guidelines written for those who started studying progr
:boy: :girl: Technical-Interview guidelines written for those who started studying programming. I wish you all the best. :space_invader: - GitHub - JaeYeopHan/Interview_Question_for_Beginner: Techn...
github.com
'다짐하자 > 출근 준비' 카테고리의 다른 글
발표 준비 - CRM과 ERP 정의와 사용 목적 / 차이점 (0) | 2023.02.01 |
---|---|
22.01.26 - [ 네트워크 ] Network (0) | 2023.01.27 |
22.01.24 - [ 개발상식 ] Development common sense (0) | 2023.01.24 |
23.01.20 ~ 01.23 - [ 설과 함께 찾아온 코로나 ] (0) | 2023.01.24 |
23.01.19 - [ 클라우드 ] 단어, 용어, 관련 지식 (0) | 2023.01.19 |