CS

자료구조 정리

hskkkk 2026. 7. 8. 19:11
  • 자료구조 - 데이터를 효율적으로 저장하고 관리하기 위한 방법
  • 알고리즘 - 어떤 목적을 이루기 위한 효율적인 연산 방법

시간복잡도

배열

  • 일정한 메모리 공간을 차지하는 여러 요소들이 순차적으로 나열된 자료구조
  • 각 요소는 0부터 시작하는 고유한 순서 번호인 index가 매겨짐, 인덱스로 배열의 요소 식별
  • 배열과 유사한 컴퓨터 부품 - RAM
    • RAM은 어떤 주소에 접근하든 접근 시간이 일정(Random Access Memory), 배열도 마찬가지
    • 인덱스를 통해 요소에 접근하는 시간은 요소의 개수와 무관하게 일정 -> O(1)
    • 앞부터 차례대로 특정 요소가 있는지를 찾는 연산 -> O(n)
    • 특정 요소 추가/삭제 
      • 삽입 혹은 삭제 연산 이후에 모든 요소들의 재정렬 가정했을때 -> O(n)

연결 리스트 (linked list) 

  • 노드의 모음으로 구성된 자료구조
  • 노드
    • 저장하고자 하는 데이터(들)
    • 다음 노드의 위치(메모리 상의 주소) 정보
  • 연결 리스트는 기본적으로 모든 노드들이 한 쪽 방향으로 꼬리에 꼬리를 무는 형태로 구성
  • 연결리스트의 첫 번째 노드는 헤드(head), 마지막 노드는 꼬리(tail)라고 부름

  • 연결 리스트를 구성하는 모든 노드는 반드시 메모리 내에 순차적으로 저장되어 있을 필요가 없음
  • 즉, 연속적으로 구성되어 있는 데이터를 불연속적으로 저장할 때 유용
  • 배열의 경우 인덱스가 주어지면 요소에 접근하는 시간이 일정하나, 연결 리스트에서 특정 요소에 접근할 때는 앞에서부터 순차적으로 접근할 수밖에 없기 때문에 O(n) 소요
  • 요소 추가 / 삭제
    • 연결 리스트는 중간에 요소를 추가하거나 삭제하는 연산에서 재정렬 불필요
    • 삽입/삭제할 노드 위치가 주어지면 위치를 막론하고 노드에 접근하는 시간이 동일하므로 O(1) 소요

연결 리스트에서 요소 추가 및 삭제

  • 싱글 연결 리스트
    • 한 쪽 방향으로 꼬리에 꼬리를 무는 형태를 띠는 기본적인 연결 리스트
    • 단방향 탐색만 가능 -> 특정 노드를 통해 다음 노드의 위치만 알 수 있고, 이전 노드의 위치는 알기 어려움
  • 이중 연결 리스트
    • 노드 내에 다음 노드의 위치 정보뿐만 아니라 이전 노드의 위치 정보도 포함 - 양방향 탐색 가능
    • 저장 공간 필요 -> 한 노드에 2개의 위치 정보(메모리 주소)를 저장함
  • 환형 연결 리스트 (원형 연결 리스트)
    • 꼬리 노드가 헤드 노드를 가리켜 노드들이 원형으로 구성된 연결 리스트
  • 이중 연결 리스트로 구현된 환형 연결 리스트
    • 헤드 노드의 이전 노드가 꼬리 노드를 가리키고, 헤드 노드의 다음 노드가 헤드 노드를 가리키도록 구성
    • 모든 노드 데이터를 여러 차례 여러 방향으로 순회해야 할 때 유용하게 활용

스택

  • 한 쪽에서만 데이터의 삽입 및 삭제가 가능한 자료구조
    • 후입선출(LIFO) 자료구조
    • push - 스택에 데이터를 저장하는 연산
    • pop - 스택에서 데이터를 빼내는 연산
    • 스택이 유용하게 사용되는 상황
      • 최근에 임시 저장한 데이터를 가장 먼저 활용해야 할 때
      • 뒤로가기 기능을 만들고 싶을 때

  • 한 쪽으로 데이터를 삽입하고, 다른 한 쪽으로 데이터를 삭제할 수 있는 자료구조
  • 선입선출(FIFO, First In First Out) 자료구조
    • enqueue - 큐의 한 쪽 끝에 데이터를 삽입하는 연산
    • dequeue - 다른 한 쪽 끝으로 데이터를 빼내는(삭제하는) 연산
  • 큐는 임시 저장된 데이터를 차례 차례 내보내거나 꺼내와야 하는 각종 버퍼(buffer)로도 활용
    • 줄 세우기에 자주 사용
    • 큐 또한 배열이나 스택처럼 다른 자료구조나 알고리즘 구현에 재료로 자주 사용
  • 원형 큐 (circular queue)
    • 데이터를 삽입하는 쪽과 삭제하는 쪽, 양쪽을 하나로 연결해 원형으로 사용하는 자료구조
  • 덱(deque) - 양방향 큐(double-ended queue)
    • 양쪽으로 데이터를 삽입/삭제할 수 있는 큐
  • 우선순위 큐(priority queue)
    • 정해진 우선순위가 높은 순으로 처리되는 큐
    • 우선순위 큐는 힙(heap) 자료구조를 기반으로 구현

해시 테이블

  • 해시 테이블 - 키와 값의 대응으로 이루어진 표(테이블)와 같은 자료구조
    • 키: 해시 테이블에 대한 입력
    • 값: 키를 통해 얻고자 하는 데이터
  • 해시 테이블의 구조와 동작
    • 키를 통해 얻고자 하는 데이터는 버킷(bucket)에 저장 
      • 버킷은 여러 개가 존재하며, 버킷들은 배열을 형성함
    • 해시 함수는 키를 인자로 버킷에 접근할 인덱스 반환
      • 키를 해시 함수에 통과시켜 원하는 버킷에 접근

  • 로드 팩터(load factor) - 해시 테이블에 저장된 데이터 수를 버킷의 수로 나눈 값
    • 해시 테이블이 현재 얼마나 가득 차있는지에 대한 지표
    • 로드 팩터가 클수록 해시 테이블의 성능이 떨어짐
  • 빠른 검색속도 -> 검색, 삽입, 삭제 연산의 시간 복잡도는 O(1), 입력과 무관하게 항상 일정한 속도 보장
    • 속도가 빠른 만큼 상대적으로 많은 메모리 공간 소모
    • 해시 충돌 문제 -> 서로 다른 키에 대해 같은 해시 값이 대응되는 상황, 보안 상의 위험 발생 가능
      • 체이닝(chaining) - 충돌이 발생한 데이터를 연결 리스트로 추가
        • 하나의 테이블 인덱스에 여러 데이터가 연결 리스트의 노드로서 존재할 수 있음
        • 서로 다른 키가 같은 위치로 해시되어도 단순히 연결 리스트 노드만 추가
        • 충돌이 발생할 때마다 연결 리스트의 노드가 추가된다면 해시 테이블의 성능 저하 우려
      • 개방 주소법(open addressing)
        • 충돌이 발생했을 때, 충돌이 발생한 버킷의 인덱스가 아닌 다른 인덱스에 데이터를 저장하는 방법
        • 조사(probe) - 충돌이 발생했을 때 비어 있는 다른 버킷의 인덱스를 찾는 과정
        • 선형 조사법(linear probing)
          • 충돌이 발생한 인덱스의 다음 인덱스부터 순차적으로 가용한 인덱스 탐색
          • 데이터의 군집화 
            • 선형 조사법의 문제
            • 해시 충돌이 발생하는 인덱스 인근에 충돌이 발생한 여러 데이터가 몰려 저장될 수 있음
            • 군집화되면 오랜 순차 탐색이 필요 -> 성능 악화
      • 이중 해싱(double hashing)
        • 2개의 해시 함수를 사용
        • 충돌이 발생 시 다른 해시 함수(보조 해시 함수) 해시 값만큼 떨어진 거리에 위치한 인덱스를 찾는 방법
        • 해시 함수를 통해 무작위로 인덱스가 생성될 수 있다면 선형 조사법의 군집화 문제를 상당 부분 피할 수 있음

좌: 체이닝, 우: 개방 주소법

  • 해시 함수(hash function)
    • 임의의 길이를 지닌 데이터를 고정된 길이의 데이터로 변환하는 단방향 함수
    • 단방향 함수이기 때문에 입력 데이터를 고정된 해시 값으로 변환할 수는 있어도 역으로 해시값을 토대로 입력 데이터를 유추하기는 어려움
    • 해시 값은 비밀번호 저장할 때도 사용
    • 무작위 값을 만들거나 단방향 암호를 만들 때, 데이터의 무결성을 검증하기 위해 사용
      1. 데이터 전송 전에 송신자가 데이터에 대한 해시값을 먼저 계산한 뒤, 이를 데이터와 함께 전송
      2. 수신자는 데이터로 해시 값을 계산한 뒤, 계산된 해시 값과 전달받은 해시 값 비교
      3. 두 값이 일치하면 바르게 전송

  • 해시 알고리즘
    • 해시 함수의 연산 방법
    • 대표적인 해시 알고리즘 - MD5, SHA-1, SHA-256, SHA-512, SHA3, HMAC 등
    • 같은 데이터라도 적용된 해시 알고리즘이 다르면 해시 값의 길이나 값이 달라짐

트리

  • 계층적 구조를 표현하기 위한 자료구조
  • 데이터가 저장되어 있는 노드, 노드와 노드를 연결하는 간선(edge) 또는 링크(link)로 구성
  • 노드는 상하 관계 형성
  • 루트 노드(root node): 부모 노드가 없는 최상단 노드
  • 리프 노드(leaf node): 더 이상의 자식 노드가 없는 최하단 노드
  • 차수(degree): 각 노드가 갖는 자식 노드의 수
  • 레벨(level): 루트 노드에서 시작해 특정 노드에 이르기까지 거치는 간선 수 
    • 트리의 깊이와 같은 개념
    • 가장 높은 레벨 = 트리의 높이
  • 서브트리(subtree): 트리 안에 포함되어 있는 트리
  • 하나의 노드를 데이터 저장 공간 + 자식 노드의 위치 정보(메모리 상의 주소) 저장동간의 모음으로 간주

 

트리의 순회

  • 트리의 모든 노드를 한 번씩 방문하는 것
  • 전위 순회
    • 루트 노드부터 시작, 왼쪽 서브트리 전위 순회, 오른쪽 서브트리 전위 순회
    • a -> b -> d -> h -> i -> e -> j -> k -> c -> f -> l -> g

  • 중위 순회
    • 왼쪽 서브트리 중위 순회 -> 루트 노드 -> 오른쪽 서브트리 중위 순회
    • h -> d -> i -> b -> j -> e -> k -> a -> l -> f -> c -> g
  • 후위 순회
    • 왼쪽 서브트리 후위 순회 -> 오른쪽 서브트리 후위 순회 -> 루트 노드
    • h -> i -> d -> j -> k -> e -> b -> l -> f -> g -> c ->a

이진 트리 (binary tree)

  • 자식 노드의 개수가 2개 이하인 트리
  • 편향 이진 트리
    • 노드 방향이 편향됨, 트리의 모든 노드가 일렬로 구성
  • 정 이진 트리 
    • 자식 노드의 개수가 1개가 아닌 이진 트리 (즉, 자식 노드의 개수가 0 또는 2개인 이진 트리)

  • 포화 이진 트리
    • 리프 노드를 제외한 모든 노드들이 자식 노드를 2개씩 가지고 있고, 모든 리프 노드의 레벨이 동일한 이진 트리
  • 완전 이진 트리
    • 마지막 레벨을 제외한 모든 레벨이 2개의 자식 노드를 가지며, 마지막 레벨의 노드들이 왼쪽부터 존재하는 이진트리

  • 이진 탐색 트리 (BST, Binary Search Tree)
    • 특정 노드의 왼쪽 서브트리에는 해당 노드보다 작은 값을 지닌 노드들이 있고, 오른쪽 서브트리에는 해당 노드보다 큰 값을 지닌 노드들이 있는 구조의 이진 트리
    • 이진 탐색 트리를 활용하면 O(log n)으로 원하는 값을 탐색 가능
    • 예외 - 편향 이진 트리의 경우 탐색 속도 O(n), 이진 탐색 트리를 이용하는 경우 최악의 상황

  • 힙(heap)
    • 탐색에 특화된 또 다른 완전 이진 트리의 일종
    • 주로 최댓값과 최솟값을 빠르게 찾기 위해 사용
    • 이진 탐색 트리와 유사하게 일반적으로 탐색에 O(log n)의 시간 복잡도가 소요
    • 최대힙 - 부모 노드가 자식 노드의 값보다 큰 값으로 이루어진 이진 트리
    • 최소힙 - 부모 노드가 자식 노드의 값보다 작은 값으로 이루어진 이진 트리
    • 우선순위 큐는 최대 힙으로 구현
      • 최대 힙을 구현 -> 최상단 루트 노드는 언제나 우선순위가 가장 높은 값을 가지게 됨
      • 우선순위 큐 저장 순서와 무관하게, 우선순위 큐에서 데이터를 빼낼 때는 우선순위가 높은 데이터 순으로 걷어낼 수 있음

 

균형을 맞추는 트리: RB 트리

  • 이진 탐색 트리의 문제점
    • 삽입, 삭제 연산을 반복하는 과정에서 트리가 한 쪽으로만 자라나는 편향된 트리가 될 수 있음
    • 같은 노드의 집합으로 트리를 만들어도, 트리를 만드는 순서에 따라 편향된 트리가 될 수 있음
      • 이 경우 편향 트리의 탐색 속도 = O(n)
      • 연결 리스트와 다를 바 없게 되고, 사실상 트리 자료구조의 사용 이유가 없어짐

  • 자가 균형 이진 탐색 트리
    • 왼쪽 서브트리와 오른쪽 서브트리 높이의 균형을 맞추는 특별한 이진 탐색 트리
    • AVL 트리 (Adelson-Velsky and Landis Tree)
    • RB 트리 (Red Black Tree)
      • RB 트리는 컴퓨터 과학 전반에 녹아 있는 근원적인 자료구조 중 하나
      • 리눅스의 CFS 스케줄러에도 RB 트리가 사용되며, 프로그래밍 언어 내부 구현에서도 RB 트리가 사용
      • 모든 노드를 빨간색 혹은 검은색으로 칠해서 균형을 유지하는 트리
      • 노드에 색상을 칠하는 규칙
        • 루트 노드는 블랙 노드
        • 리프 노드는 블랙 노드
        • 레드 노드의 자식 노드는 블랙 노드
        • 어떤 노드에서 리프 노드에 이르는 경로 속 블랙 노드 수는 같음
        • 새로운 노드 삽입(*삽입 노드는 레드 노드) 시 RB 트리에 부합하지 않게 되면, 색상을 재지정하거나 트리의 회전으로 부합하게 만듦

대용량 입출력을 위한 트리: B 트리

  • B트리는 다진 탐색 트리의 일종
    • 다진 탐색 트리: 한 노드가 여러 자식 노드를 가질 수 있는 탐색 트리
    • B 트리의 한 노드가 가질 수 있는 최소/최대 자식 노드 수는 정해져 있음
    • M차 B 트리 -> 한 노드가 가질 수 있는 최대 자식 노드의 개수가 M개인 B 트리
    • M차 B트리가 가질 수 있는 최소 자식 노드의 개수는 [M/2]개
      • 루트, 리프 노드를 제외
      • ex) 5차 B트리 -> 최대 5개의 자식 노드, (루트, 리프 노드를 제외한) 노드들은 최소 3개의 자식 노드를 가질 수 있음
  • B 트리의 각 노드에는 하나 이상의 키값이 존재하고, 각 키들이 오름차순으로 저장
    • 일반적으로 키는 데이터를 찾을 인덱스로 활용
    • 키가 N개인 노드가 가질 수 있는 자식 노드의 수는 반드시 N+1개

  • B트리의 활용 -> 파일 시스템, 데이터베이스와 같이 대량의 데이터를 기반으로 탐색, 접근, 저장을 수행할 때 활용
    • 최소한의 입출력 연산으로 파일 시스템, 데이터베이스 데이터 탐색/접근/저장
  • B+ 트리(B트리의 변형)
    • B+ 트리에서는 실질적인 데이터가 모두 최하위 리프 노드에 위치
    • 최하위 리프 노드는 연결 리스트로 구성 -> 다른 리프 노드들 간의 범위 연산 용이

그래프

  • 정점(vertex)을 간선(edge) 혹은 링크(link)로 연결한 형태의 자료구조
  • 연결 관계를 표현하는 자료구조
  • 트리도 그래프의 일종
    • 트리는 사이클을 형성하지 않고 연결된 노드 간에 상하 관계를 가짐 (계층적 구조)
    • 그래프는 사이클을 형성할 수 있고, 이웃한 정점까지 상하 관계를 갖지도 않음(더 일반적인 연결 관계 표현)

  • 연결 그래프 - 그래프 상에 있는 임의의 두 정점 사이의 경로가 존재
  • 비연결 그래프 - 어떤 정점 사이에는 경로가 존재하지 않음
  • 방향 그래프 - 간선에 방향이 있는 그래프
  • 무방향 그래프 - 방향이 없는 그래프 (사실상 양방향 그래프)
  • 가중치 그래프
    • 간선에 가중치가 부여된 그래프
    • 간선에 부여된 값인 가중치는 비용이라고도 함
    • 간선에 부여할 수 있는 값이라면 양수, 음수 모두 가능
  • 서브 그래프 - 부분 그래프
    • 특정 그래프의 정점과 간선의 일부분으로 이루어진 그래프

그래프의 구현 방법

  • 인접 행렬로 표현 -> 이차원 배열을 기반으로 그래프를 구현
    • N은 정점의 개수
    • N*N 크기의 행렬로 그래프를 표현하는 방법
    • N*N 행렬의 <행, 열> 값은 <출발 정점, 도착 정점>
    • 두 정점이 단순히 연결되었을 때는 1, 연결되지 않았을 때는 0으로 표기
    • 가중치 그래프의 경우, 행렬에 가중치를 기입

정점의 개수가 4개이므로 4*4 크기의 이차원 배열로 나타낼 수 있음

  • 인접 리스트로 표현 -> 연결 리스트를 기반으로 구현
    • 가중치 그래프의 경우 간선에 연결된 노드 정보뿐 아니라 간선에 할당된 가중치까지 함께 하나의 노드로 표현

 

그래프 기반 연산

1. 깊이 우선 탐색 (DFS, Depth-First Search)

  • 그래프에서 더 이상 방문 가능한 정점이 없을 때까지 최대한 깊이 탐색하기를 반복하는 탐색 방법

a -> b -> e -> c -> f -> d

  • 깊이 우선 탐색 구현
    • 정점 a 부터 탐색을 시작 -> 인접한 정점이 2개 이상일 경우에는 알파벳 순으로 탐색한다고 가정
    • 배열 & 스택: 깊이 우선 탐색 알고리즘 구현 시 활용
      • 배열: 특정 정점의 방문 여부를 확인 -> 미방문 정점을 파악하기 위해 방문한 적이 있는 정점들을 배열로 관리
      • 스택: 정점 방문 도중 뒤로가기가 필요할 때 사용 (위 이미지의 그래프에선, 노드 방문 시 push, 해당 노드와 연결된 간선이 없을 때 pop)

2. 너비 우선 탐색 (BFS, Breadth-First Search)

a -> b -> c -> d -> e -> f

  • 최대한 넓게 탐색하기를 반복하는 탐색 방법
  • 배열 & 큐: 너비 우선 탐색 알고리즘 구현 시 활용
    • 배열: 특정 정점의 방문 여부를 확인
    • 큐: 연결된 정점들을 줄 세우듯 저장

'CS' 카테고리의 다른 글

[운영체제] 파일과 디렉터리  (0) 2026.07.08
[운영체제] 가상 메모리, 페이지 교체  (0) 2026.07.08
[운영체제] 교착 상태  (0) 2026.07.06
[운영체제] 프로세스 동기화  (0) 2026.07.06
[운영체제] CPU 스케줄링  (0) 2026.07.04