this week i learned..
2주차 학습 내용
- 컴퓨터 시스템 책(Compouter Systems - A Programmer's Perspective / CSAPP) 1.5 - 1.7
- 백준 문제 풀이 + 관련 이론 학습
- 스택
- 큐
- 우선순위 큐
CSAPP 1.5 - 1.7
캐시가 중요하다
- 시스템이 정보를 한 곳에서 다른 곳으로 이동시키는 데 많은 시간이 든다.
- 하드디스크에서 메인 메모리로, 그리고 메인 메모리에서 프로세서로..
- 이러한 복사 과정들은 프로그램의 "실제 작업"을 느리게 하는 오버헤드(overhead)가 된다.
- 오버헤드: 어떤 처리를 함에 있어서, 간접적인 원인으로 인해 추가되는 처리 시간 및 메모리
- 큰 저장장치들은 작은 저장장치들보다 느린 속도를 갖는다. 그리고 빠른 장치들은 느린 장치들보다 만드는 데 더 많은 비용이 든다. (trade-off)
- 캐시 메모리: 프로세서가 단기간에 필요로 할 가능성이 높은 정보를 임시 저장할 목적으로 사용
저장장치들은 계층구조를 이룬다
- 메모리 계층 구조
- 저장장치들은 아래 그림과 같은 메모리 계층구조를 이루는데, 계층구조의 위에서 아래로 갈수록 저장장치들은 더 느리고/더 크고/더 저렴해진다.
- 한 레벨의 저장장치가 다음 하위레벨 저장장치의 캐시 역할을 한다.
운영체제는 하드웨어를 관리한다
- 운영체제: 하드웨어/소프트웨어 사이에 위치한 소프트웨어 계층
- 프로그램은 메모리에 직접 접근하지 않는다. 대신 운영체제가 제공하는 서비스를 활용한다.
- 응용프로그램이 하드웨어를 제어하려면 운영체제를 통해서 해야 한다.
- 운영체제의 두 가지 목적
- 첫 번째, 응용프로그램들이 하드웨어를 잘못 사용하는 것을 막기 위함.
- 두 번째, 응용프로그램들이 하드웨어 장치들을 비교적 단순한 메커니즘을 사용하여 조작할 수 있도록 하기 위함.
- 운영체제는 이를 위해 추상화를 사용한다.
- 입출력장치의 추상화 → 파일
- 메인 메모리, 디스크 입출력 장치의 추상화 → 가상메모리
- 프로세서, 메인 메모리, 입출력장치 모두의 추상화 → 프로세스
자료구조, 알고리즘
스택, 큐
- 스택(stack)
- 후입선출(LIFO)의 특징을 가진다. → 데이터가 입력 순서의 역순으로 처리되어야 할 때 사용
- 함수의 콜 스택(function call stack)이 대표적인 사례
- 예를 들어 DFS를 구현할 때, 배열로 스택을 구현하는 방식으로 코드를 짤 수도 있지만 재귀 함수를 사용하여 아예 함수 콜 스택 자체를 이용하는 방식도 가능하다.
- 스택의 연산: push, pop, peek, empty
- push: 데이터를 스택에 넣는 것을 의미하는데, 이때 스택의 크기 이상으로 데이터를 push하게 되면 stack overflow가 발생
- pop: 데이터를 삭제하는 연산과 해당 데이터를 반환 받는 연산으로 이루어져 있음. 스택에 있던 데이터보다 더 많이 pop을 하게 될 경우 underflow가 발생
- peek: 데이터를 삭제하지 않고 확인만 하는 연산
- empty: 스택이 비어있는지 확인
- 큐(queue)
- 선입선출(FIFO)의 특징을 가진다. → 입력된 데이터가 순서대로 처리되어야 할 때 사용
- 예를 들어 네트워크 요청은 요청 큐에 들어온 순서대로 처리가 된다.
- 큐에서 다음에 값이 들어올 인덱스를 리어(rear)라고 하고, 이제 반환될 값의 인덱스를 프론트(front)라고 한다.
- 큐의 연산: enqueue, dequeue, peek
- enqueue: 데이터를 리어로 삽입함. enqueue가 되는 순간 리어는 다음 인덱스로 이동
- dequeue: 데이터를 프론트에서 꺼냄. dequeue가 되는 순간 프론트는 다음 인덱스로 이동
- peek: 프론트에 있는 자료를 반환하되 dequeue와 달리 삭제는 하지 않음.
힙 정렬
- 힙 정렬은 힙(max heap)에서 최댓값은 루트에 위치한다는 힙의 특징을 이용하여 정렬하는 알고리즘이다.
- 힙 정렬을 할 때 다음의 작업을 반복:
- 힙에서 루트(최댓값)을 꺼낸다.
- 루트 이외의 부분을 힙으로 만든다. → heapify
- 이러한 반복 작업을 거치면서 꺼냈던 값들을 나열하면 정렬이 끝난 배열이 완성된다.
- 힙 정렬은 선택 정렬(selection sort)을 응용한 알고리즘이다.
선택 정렬
- 0번째 원소부터 주목한다.
- 배열을 순회하며, 최소값을 갖는 원소를 찾는다.
- 최소값 원소와, 주목 중인 원소를 swap 한다.
- 이제 1번째 원소에 주목하여 같은 작업을 반복한다. n번째 원소까지 동일하게 진행된다.
힙(heap)
- 힙: 부모의 값이 자식의 값보다 항상 크다는 조건을 만족하는 완전 이진 트리
- 부모 값은 자식 값보다 항상 작아도 됨.
- 항상 크든 작든, 부모 값과 자식 값의 대소 관계가 일정하기만 하면 됨.
- 완전 이진 트리
- 우선 트리🌲란, 각 원소를 의미하는 노드(node)들이 연결된 계층 구조다.
- 트리의 가장 윗부분에 위치한 루트(root)는 부모가 없는 노드다.
- 노드 간의 관계
- 노드 간 상하 관계: 부모 노드(parent node)-자식 노드(child node)
- 부모가 같은 자식 노드 간의 관계: 형제 노드(sibling node)
- 완전 이진 트리는 트리의 한 종류인데, 이름에서 알 수 있듯이 완전 이진 상태라는 특징이 있다.
- 완전: 부모는 왼쪽 자식부터 추가하여 모양을 유지한다.
- 이진: 부모가 가질 수 있는 자식의 최대 개수는 2개 뿐이다.
- 힙에선 부모의 값이 자식의 값보다 항상 큰 관계가 성립하기 때문에, 힙의 가장 위쪽에 위치한 루트가 힙에서 가장 큰 값이 된다.
- 힙에 대해 알기 전에 ADT인 우선순위 큐에 대해 알아야 한다.
- ADT(Abstract Data Type, 추상 자료형)
- 자료 구조의 기반으로, 값과 연산의 집합으로 정의되는 논리적 행동을 가지는 object class
- 추상 ↔️ 구상(concrete)
- ADT vs 자료 구조: 가장 큰 차이점은 바로 구현 여부
- 구현 명세가 있으면 자료 구조, 없으면 추상 자료형
- 이미 구현이 되어있는 것은 자료 구조
- 우선순위 큐(priority queue)
- 일반적인 큐와 같이 FIFO에 따라 동작하는 것이 아니라, 일정한 규칙에 맞춰 동작하는 큐
- 인큐할 때 데이터에 우선순위를 부여하여 추가하며, 디큐할 때 우선순위가 높은 데이터를 꺼낸다.
- ADT(Abstract Data Type, 추상 자료형)
- 힙은 일반적으로 이진 트리(binary tree)로 구현된다.
- max heap(부모 값 > 자식 값)은 가장 큰 숫자를 먼저 빼주는 반면, min heap(부모 값 < 자식 값)은 가장 작은 값을 먼저 빼준다.
- 시간복잡도
- 최대값(최소값) 접근: O(1)
- 최대값(최소값)은 이진 트리의 루트에 위치해있기 때문
- 새로운 노드를 추가하게 될 경우: O(logN)
- 기존 노드들과 크기를 비교하면서 swap 작업을 진행
- 루트 삭제하며 힙 재구성: O(logN)
- 최대값(최소값) 접근: O(1)
- 완전 이진 트리의 성질을 이용해서 트리가 아닌 배열로도 힙을 표현할 수 있다.
- 힙의 원소를 어떤 배열(a)에 저장하는 방법은 다음과 같다. :
- 루트를 a[0]에 저장한다.
- 한 단계 아래로 내려가되, 왼쪽 노드부터 본다. 왼쪽 노드의 값을 a[1]에 저장한다. 그 다음에 같은 단계의 오른쪽 노드를 본다. 인덱스를 1 증가시킨 a[2]에 오른쪽 노드의 값을 저장한다.
- 인덱스 값을 1씩 증가시키며, 왼쪽부터 오른쪽으로, 한 단계 완료되면 그 다음 단계의 왼쪽 노드로 가면서 해당 노드의 값을 배열에 저장하는 작업을 반복한다.
- 이러한 순서에 따라 힙을 배열로 나타나게 되면 어떤 원소 a[i]의 인덱스 i와 그 부모 인덱스 및 자식 인덱스 간에는 다음과 같은 관계가 성립하게 된다. :
- 부모 인덱스: (i - 1) // 2
- 왼쪽 자식 인덱스: (i * 2) + 1
- 오른쪽 자식 인덱스: (i * 2) + 2 → 즉, 왼쪽 자식 인덱스 + 1
- 힙의 원소를 어떤 배열(a)에 저장하는 방법은 다음과 같다. :
- 힙에서 부모 자식 관계는 일정하지만, 형제 사이의 대소 관계는 일정하지 않다.
- 이처럼 힙은 형제 대소 관계가 정해져 있지 않으므로, 부분 순서 트리(partial ordered tree)라고도 한다.
문제 접근 방식
- 2805. 나무 자르기 🌳 - 0부터 가장 높은 나무 높이까지 1씩 증가하며 적절한 높이를 찾아가는 방법도 있지만 이러한 방법은 O(n^2)의 시간 복잡도를 갖기 때문에 이진 탐색을 사용하는 편이 좋다.
- 2470. 두 용액 🧑🔬 - 정렬되어 있는 수열에서 특정 합을 구하는 문제를 보면 투 포인터를 떠올리자.
- 11053. 가장 긴 증가하는 부분 수열 - LIS(Longest Increasing Subsequence) 유형은 흔한 유형이다. DP로 해결하는 게 좋다.
- dp[i]는 A[i]까지의 부분 수열 길이
2주차 소회
코로나 이슈로 인해 공부도 거의 못하고 문제도 문제꾸러미 중에서 절반 정도 밖에 못 풀었다. (심지어 twil도 이제야 올림;;)
이틀은 정말 앉아있는 것도 힘들 정도로 아파서 어쩔 수 없었다해도, 격리 3일차부터는 그 정도는 아니었지만서도 어쩐지 뇌가 고장난 것처럼 도저히 집중이 되지 않았다. 그 상태로 기숙사 방에서 혼자 공부하려고 하니까 자꾸 쉬거나 딴 짓을 하게 됐다.. (다나카 영상 진짜 많이 봤다..;) 그리고 팀원분과 비대면으로 협업을 진행하기가 마땅치 않아서 거의 혼자 학습을 했던 것도 상당히 아쉽고 팀원분께 죄송했다 ㅠ
그렇지만..! 한편으론 5개월 중 그나마 제일 덜 바쁜 1~4주차 중에 미리 걸려서 오히려 다행인 것 같기도 하고..!? 🤭
'학습 내용 > 크래프톤 정글' 카테고리의 다른 글
크래프톤 정글 4, 5주차 회고 (2) | 2022.12.23 |
---|---|
CSAPP 9장. 가상메모리 - 9.1 ~ 9.8 내용 정리 (2) | 2022.12.05 |
크래프톤 정글 3주차 TWIL.. (1) | 2022.12.01 |
크래프톤 정글 1주차 TWIL.. (3) | 2022.11.05 |
크래프톤 정글 1주차 에세이 (8) | 2022.10.31 |