인프런 워밍업 클럽 스터디 3기 - CS 전공지식 <1주차 발자국>

인프런 워밍업 클럽 스터디 3기 - CS 전공지식 <1주차 발자국>

'그림으로 쉽게 배우는 운영체제'


[섹션 01]

운영체제란??

컴퓨터의 하드웨어적인 요소들과 소프트웨어적인 요소들을 효율적으로 운영하여 관리함으로써 사용자가 시스템을 이용하는데에 편리함을 제공하는 시스템 소프트웨어를 말합니다.


운영체제 종류 및 특징

 

  • 유닉스/리눅스

    • 대화식 운영체제

      • 사용자가 명령을 입력하면 시스템이 명령을 수행

    • 다중작업

      • 한번에 하나 이상의 작업을 수행할 수 있음

    • 다중 사용자

      • 여러 사람이 동시에 각각 작업을 수행할 수 있음

    • 이식성

      • 90%이상 C언어로 구성, 시스템이 모듈화 되어 있어 다른 하드웨어 기종에 쉽게 이식 가능

    • 계층적 파일 시스템 제공

      • 계층적 트리 구조를 가짐

    • 유닉스와 리눅스의 차이점

      • 리눅스는 대부분 무료이지만 유닉스는 대부분 유료

      • 리눅스는 개발자 및 일반 사용자가 사용, 유닉스는 대형 시스템 관리자가 사용

      • 리눅스는 오픈 소스 개발, 유닉스는 사업자에 의해 배포 비용 수반

      • 리눅스는 BASH 쉘 사용, 유닉스는 커맨드 기반

 

  • 윈도우

    • 그래픽 사용자 인터페이스(GUI) 제공

      • 키보드없이 마우스로 아이콘이나 메뉴를 선택하여 작업 수행 가능

    • 선점형 멀티 태스킹 방식 제공

      • 동시에 여러개의 프로그램을 실행하며, 운영체제가 각 작업의 CPU 이용시간 제어

    • 자동 감지 기능 (Plug & Play)

      • 하필요한 시스템 환경을 운영체제가 자동으로 구성

    • OLE(Object Linking and Embedding) 사용

      • 개체를 현재 작성 중인 문서에 자유롭게 연결 또는 삽입 가능

 

  • IOS

    • iOS는 사용자 경험과 인터페이스에 매우 중점을 둠

    • 하드웨어 및 소프트웨어 최적화

    • 강력한 보안 및 프라이버시 기능

    • OS는 앱스토어를 통해 다양한 애플리케이션을 제공하며, 개발자들에게 큰 수익 창출의 기회를 제공

     


 

운영체제 특징

  • 사용자 편리성

    • 한정된 시스템 자원을 효과적으로 사용할 수 있도록 관리 및 운영

  • 인터페이스 기능

    • 컴퓨터 시스템과 사용자를 연결

  • 스케줄링

    • 자원의 현재 상태를 파악, 자원 분배를 위한 스케줄링을 담당

  • 자원관리

    • 프로세스 관리

    • 메모리 관리

    • 하드웨어 관리

    • 파일 시스템 관리

    • 입출력 프로그램 관리

  • 제어기능

    • 입출력 장치와 사용자 프로그램을 제어

 


운영체제 역사

 

  • 1940년도

    • 애니악 개발

      • 애니악 특징

        • 운영체제가 없는 최초의 컴퓨터

        • 응용 프로그램이 시스템 자원을 제어

        • 스위치와 배선을 연결해서 프로그래밍

        • 문제 발생 시 종이에 작업 후 테스트 마침 => 기간이 많이 소모되는 단점

        • 30톤으로 수많은 진공관으로 구성되어 있기 때문에, 하드웨어 비용이 굉장히 비쌈

     

  • 1950년대 초

    • 진공관과 전선으로 만들어진 논리 회로를 아주 작은 크기로 만든 직접회로 개발

    • CPU와 메모리가 존재하지만 키보드와 모니토는 존재하지 않음

    • 펀치 카드에 프로그래머가 카드의 구멍을 뚫어 프로그래밍

      • 컴퓨터가 카드를 읽고 계산 후 결과를 라인 프린터로 출력

    • 기존 스위치 배선 작업보다 편해짐

 

  • 1950년도 중후반

    • 이전 작업은 오퍼레이터의 오버헤드가 너무 큼

    • 싱글 스트림 배치 시스템 개발

      • 여러개의 프로그램을 순서대로 실행해서 결과를 한번에 확인할 수 있는 시스템

         

    • I/O Device 컨트롤러를 만들어 입출력 중에도 CPU가 계산할 수 있도록 만듦

    • 입출력 작업이 끝나면 CPU에게 인터럽트 신호를 주고 인터럽트를 받은 CPU는 다시 처리를 하는 식으로 발전

    • 입출력에도 CPU를 기다려야 하는 작업이 필요하다는 단점이 있음

       

       

     

  • 1960년도 이후

    • 메모리 침범 이슈 발생

    • 다중 프로그램으로 인한 메모리 주소 이슈 발생

    • 하드웨어적으로 베이스 레지스터라는 것을 추가해서 프로그램의 시작 주소를 저장하고 모든 프로그램은 영번지에서 실행한다고 가정

    • CPU의 사용률과 효율성을 중요한 문제로 인식

 

  • 1970년도 이후

    • 개인용 컴퓨터의 시대가 시작

    • 저렴해진 컴퓨터의 개인 소유가 쉬워짐

    • 애플의 매킨토시와 마이크로소프트의 MS-DOS가 많이 사용

    • 매킨토시는 GUI를 도입해서 굉장한 인기

    • CPU 사용률과 비용 절감을 위한 노력으로 오늘날의 운영체제가 탄생

       


 

운영체제의 구조

  • 커널

    • 운영체제의 핵심 기능들이 모여있는 컴퓨터 프로그램

      • 커널의 기능

        • 프로세스 관리

        • 기억 장치 관리

        • 주변장치 관리

        • 파일 관리

      • 사용자로부터 자신을 보호하기 위한 시스템 콜이라는 인터페이스 보유

      • 시스템 콜을 이용하면 커널에서 제공하는 write() 함수를 쓰게 되는데 하드디스크의 빈 공간에 저장

 

  • 인터페이스

    • GUI

      • 그래픽 사용자 인터페이스의 약자로 말 그대로 그래픽으로 된 인터페이스

      • 윈도우나 맥OS와 같이 그래픽으로 커널과 상호작용하기 때문에 일반 사용자도 사용하기가 쉬움

       

    • CLI

      • 명령줄 인터페이스의 약자

      • 요즘은 리눅스는 GUI 환경을 제공하지만 많은 사용자들이 리눅스의 CLI를 선호

     


컴퓨터 하드웨어와 구조

  • 현재 컴퓨터는 프로그램 내장 방식의 폰 노이만 구조

    • 폰 노이만은 CPU와 메모리 사이를 버로 연결함

      • 버스는 데이터를 전달하는 통로

    • 프로그램 내장 방식은 프로그램을 메모리에 올려서 실행시키는 방식

  • 메인보드

    • 다른 하드웨어를 연결하는 장치

    • 다양한 단자가 있음

      • ex) 출력단자, 그래픽 카드 단자, USB 단자, 사운드 단자 등등

    • 장치간의 데이터를 전송하는건 메인보드의 버스가 담당

  • CPU

    • 1. 산술논리 연산 장치

      • 데이터 연산 담당

    • 2. 제어 장치

      • 모든 장치들의 동작 지시 및 제어

    • 3. 레지스터

      • CPU 내에서 계산을 위해 임시적으로 보관하는 장소

         

  • RAM

    • 랜덤으로 데이터를 읽어도 저장된 위치와 상관 없이 읽는 속도가 동일

    • 전력이 끊기면 데이터를 잃어버리기 때문에 메인 메모리로 사용

     

  • ROM

    • 전력이 끊겨도 데이터 영구 보관

    • 데이터를 한번 쓰면 수정 불가

     

     


컴퓨터 부팅 과정

  • ROM에 저장된 BIOS 가 실행됨

    • 바이오스 - BIOS (Basic Input Output System)

      • 메모리와 CPU 레지스터를 초기화 시킨다.

      • 디스크로부터 부트 로더를 불러 온다

      • 바이오스는 롬에 저장되어 있기 때문에 램에 저장된 정보와는 달리, 컴퓨터를 끄더라도 그 내용이 지워지지 않음

         

       

  • 주요 하드웨어에 이상이 없는지 확인 후 부팅

     

    • 이상이 있을 경우 경고음을 내면서 부팅이되지 않음

    • 운영체제가 2개 설치되어 있을 경우, 운영체제를 선택하는 화면이 활성화됨

       

  • 부팅 후 실행되는 모든 프로그램은 램에 올라와서 운영체제에 의해 관리 

 


폴딩

  • 주기적으로 CPU가 입출력 관리자에게 주기적이고 지속적으로 입출력이 왔는지 확인

  • 폴링 방식의 단점은 주기적으로 CPU가 확인해줘야 하니 성능이 좋지 않다는 단점이 존재

     

     

     

     


인터럽트

  • 폴링 방식의 단점을 해결한 방식

  • 입출력이 완료되었을 때 CPU에게 신호를 주어 인터럽트 서비스 루틴을 실행하는 방식

    • 서비스루틴 이란?

      • 특정 인터럽트가 들어오면 그 인터럽트를 처리하는 함수

     


 

[섹션 02]

프로그램이란?

  • 하드디스크 등과 같은 저장장치에 저장된 명령문의 집합체

 


프로세스란?

  • 하드디스크에 저장된 프로그램이 메모리에 올라갔을 때 실행중인 프로그램

  • 메모리도 사용하고 운영체제의 CPU 스케줄링 알고리즘에 따라서 CPU도 사용하고 필요에 따라 입력과 출력을 하기 때문에 능동적인 존재

  • 코드 영역, 데이터 영역, 스택 영역, 킵 영역을 갖고 있음

    • 코드 영역

      • 자신을 실행하는 코드가 저장되어 있고 데이터 영역은 전역 변수와 스태틱 변수가 저장

    • 스택 영역

      • 지역 변수와 함수 호출을 했을 때 필요한 정보들이 저장

    • 힙 영역

      • 프로그래머가 동적으로 메모리를 할당

      • ex) C언어에서 malloc, free 함수를 호출하면 힙 영역에 자원을 할당, 해제

 


컴파일 과정

고급 언어(예: C, C++)로 작성된 소스 코드를 기계어(바이너리 코드)로 변환하는 과정
4단계(전처리 → 컴파일 → 어셈블 → 링크)로 진행

 

1. 전처리 (Preprocessing)

  • 소스 코드에서 전처리 지시문(#으로 시작하는 문장)을 처리하는 단계

  • 생성 파일 : .i 로 끝남

     

2. 컴파일 (Compilation)

  • 전처리된 코드를 어셈블리 코드(assembly language)로 변환하는 단계

  • 생성 파일 : .s 로 끝남

  • 주요 작업

    • 문법 검사 및 오류 확인

    • 최적화 수행

    • 어셈블리 코드 생성

       

3.어셈블 (Assembling)

  • 어셈블리 코드를 기계어(오브젝트 파일, .o 또는 .obj)로 변환하는 단계입니다.

  • 생성 파일 : .o 로 끝남

주요 작업

  • 명령어를 바이너리 코드로 변환

  • 오브젝트 파일 생성

4. 링크 (Linking)

  • 여러 개의 오브젝트 파일과 라이브러리를 결합하여 실행 파일(Executable, .exe 또는 a.out)을 생성하는 단계

  • 생성 파일 : .exe, .out 로 끝남

     

     


멀티 프로그래밍과 멀티 프로세싱

  •  멀티 프로그래밍

    • 하나의 CPU가 여러 프로세스를 번갈아 실행

    • 특징

      • CPU 이용률 극대화

      • 비선점형 스케줄링에 많이 사용

      • 병렬 처리가 아닌 시분할 방식

     

  • 멀티 프로세싱

    • 여러 개의 CPU가 동시에 여러 프로세스를 처리

    • 특징

      • 병렬 처리 가능

      • 선점형 스케줄링 적용

      • 다중 코어 시스템에서 사용


PCB (Process Control Block)

  • 운영체제가 각 프로세스를 관리하기 위해 유지하는 데이터 구조체

  • 프로세스의 상태, 메모리 정보, CPU 레지스터 정보 등을 저장

  • 구성 요소

    • PID (Process ID)

    • 프로세스 상태

    • 프로그램 카운터

    • CPU 레지스터

    • 메모리 관리 정보

    • 입출력 상태 정보

    • 우선순위

 프로그램 카운터가 필요한 이유는 어떤 프로세스가 실행되다가 다른 프로세스에게 CPU를 뺏기고 다시 실행될 때 원래 실행하던 명령어가 실행되어야 하기 때문에 프로그램 카운터가 꼭 있어야 함

 


프로세스 상태

1. 생성

  • 새로운 프로세스 생성

     

     

     

     

     

     

     

    2. 준비

  • CPU 할당을 기다리는 상태

     

3.실행

  • CPU가 프로세스를 실행 중

4.대기

  • /O 작업 등으로 대기 중

5. 완료

  • 실행이 끝난 상태


컨텍스트 스위칭 (Context Switching)

  • CPU가 현재 실행 중인 프로세스를 중단하고, 다른 프로세스로 전환하는 작업

  • PCB에 현재 프로세스의 상태 정보를 저장하고, 다음 프로세스의 상태 정보를 불러옴

  • 절차

    • 1. 현재 프로세스의 상태 저장 (PCB)

    • 2. 새로운 프로세스의 PCB 불러오기

    • 3. CPU 레지스터 및 메모리 정보 복원

    • 4. 새로운 프로세스 실행

 


프로세스 생성과 종료

  • 프로세스 생성 과정

    • 1. 부모 프로세스가 fork() 또는 CreateProcess() 호출

    • 2. 운영체제가 PCB 생성

    • 3. 메모리 할당 및 초기화

    • 4. Ready 상태로 전환

  • 프로세스 종료 과정

    • 1. 프로세스 작업 완료 또는 오류 발생

    • 2. 운영체제가 자원 회수

    • 3. PCB 제거

    • 4. Terminated 상태로 전환

 


쓰레드 (Thread)

  • 프로세스 내에서 실행 흐름 단위

  • 독립적인 스택과 레지스터를 가짐

  • 같은 프로세스의 쓰레드는 코드, 데이터, 힙 영역 공유

  • 쓰레드 종류

    • 커널 레벨 쓰레드: 운영체제에서 관리

    • 유저 레벨 쓰레드: 사용자 공간에서 관리

 

 


[섹션 03]

 CPU 스케줄링 이란?

  • CPU 스케줄링은 운영체제가 CPU를 여러 프로세스에게 효율적으로 할당하는 기법

  • 이는 시스템 성능을 최적화하고 공정성을 보장하며, 응답 시간과 처리율을 개선하는 역할

     

     

 


2. 스케줄링 목표

  • CPU 이용률

    • CPU를 최대한 활용하도록 함

  • 처리량

    • 단위 시간당 처리할 수 있는 프로세스 수를 최대화

  • 대기 시간 최소화

    • 프로세스가 CPU를 기다리는 시간을 줄임

  • 응답 시간 최소화

    • 사용자의 요청에 빠르게 반응

  • 공정성

    • 모든 프로세스가 공정하게 CPU를 할당받도록 보장

     


다중 큐 (Multi-Queue)

  • 다중 큐 스케줄링은 프로세스를 여러 개의 큐로 분류하고, 각 큐에 다른 스케줄링 정책을 적용하는 방식

    • ex) 시스템 프로세스는 높은 우선순위를 가진 큐에서 실행되고, 사용자 프로세스는 낮은 우선순위 큐에서 실행

       

       


FIFO (First In First Out)

  • 먼저 들어온 프로세스가 먼저 실행됨 (큐의 구조와 유사)

  • 장점: 구현이 간단함

  • 단점: 짧은 작업보다 긴 작업이 먼저 실행되면 Convoy Effect 발생 (짧은 작업이 뒤에서 오래 대기하는 문제)

 


SJF (Shortest Job First)

  • 실행 시간이 가장 짧은 프로세스를 먼저 실행

  • 장점: 평균 대기 시간을 최소화

  • 단점: 실행 시간이 긴 프로세스가 계속 뒤로 밀려 기아 현상(Starvation) 발생 가능

 


타임 슬라이스 (Time Slice)란?

  • 타임 슬라이스는 CPU가 각 프로세스에 할당하는 최대 실행 시간을 의미

  • 타임 퀀텀(Time Quantum) 이라고도 부르며, 보통 밀리초(ms) 단위로 설정

  • 한 프로세스가 타임 슬라이스만큼 실행된 후, 문맥 전환(Context Switch) 을 통해 다른 프로세스로 넘어감

 


타임 슬라이스의 특징

  • 짧은 타임 슬라이스

    • 빠른 응답성을 제공하지만 문맥 전환 비용이 증가

  • 긴 타임 슬라이스

    • 문맥 전환 비용이 줄지만 응답 시간이 길어짐

  • 적절한 타임 슬라이스 값을 설정하는 것이 중요

  • 일반적으로 타임 슬라이스는 문맥 전환 비용보다 충분히 커야 효율적

 

타임 슬라이스가 적용되는 스케줄링 알고리즘

  • 1. RR (Round Robin)

  • 2. MLFQ (Multi-Level Feedback Queue)

 


RR (Round Robin)

  • 일정한 시간동안 프로세스를 실행한 후, 다음 프로세스로 전환

     

  • 장점: 공정성이 보장됨 (모든 프로세스가 CPU를 일정 시간 동안 사용할 기회 제공)

  • 단점: 시간 할당량이 너무 크면 FIFO와 유사해지고, 너무 작으면 문맥 전환(Context Switch) 비용 증가

 


MLFQ (Multi-Level Feedback Queue)

  • 여러 개의 큐를 사용하여, 우선순위를 동적으로 조정하는 방식

     

    • 처음에는 높은 우선순위 큐에서 실행

    • CPU를 많이 사용하면 낮은 우선순위 큐로 이동

    • I/O 중심 프로세스는 높은 우선순위를 유지

       

  • 장점: CPU 및 I/O 중심 프로세스를 균형 있게 처리할 수 있음

  • 단점: 정책을 잘못 설계하면 특정 프로세스가 기아 상태에 빠질 가능성이 있음

 

 


'그림으로 쉽게 배우는 자료구조와 알고리즘(기본편)'

 

자료구조와 알고리즘이란?

  • 자료구조(Data Structure): 데이터를 효율적으로 저장하고 관리하는 방법

  • 알고리즘(Algorithm): 문제를 해결하는 절차나 방법

 


시간 복잡도(Time Complexity)란?

  • 알고리즘이 실행되는 연산 횟수를 입력 크기(n)에 따라 분석한 것

  • 주로 빅오 표기법(O-notation)으로 표현

image


배열(Array) 개념

  • 같은 자료형의 연속된 메모리 공간을 차지하는 데이터 구조

  • 빠른 접근(O(1)) 가능, 하지만 삽입/삭제(O(N))이 느림

 

배열 구현

#include <iostream>
using namespace std;

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    
    cout << "배열 요소 출력: ";
    for(int i = 0; i < 5; i++) {
        cout << arr[i] << " ";
    }
    
    return 0;
}

 


연결 리스트(Linked List) 개념

  • 노드(Node)들이 포인터로 연결된 구조

  • 삽입/삭제가 빠름(O(1)), 접근 속도가 느림(O(N))

  • 단일 연결 리스트(Singly Linked List), 이중 연결 리스트(Doubly Linked List) 등이 있음

연결리스트 구현

#include <iostream>
using namespace std;

struct Node {
    int data;
    Node* next;
    Node(int val) : data(val), next(nullptr) {}
};

class LinkedList {
public:
    Node* head;
    
    LinkedList() : head(nullptr) {}

    void insert(int data) {
        Node* newNode = new Node(data);
        newNode->next = head;
        head = newNode;
    }

    void remove(int data) {
        Node* temp = head;
        Node* prev = nullptr;
        
        while (temp && temp->data != data) {
            prev = temp;
            temp = temp->next;
        }
        
        if (!temp) return; // 삭제할 노드 없음

        if (prev) prev->next = temp->next;
        else head = temp->next; // 첫 번째 노드 삭제 시
        
        delete temp;
    }

    void display() {
        Node* temp = head;
        while (temp) {
            cout << temp->data << " -> ";
            temp = temp->next;
        }
        cout << "NULL\n";
    }
};

int main() {
    LinkedList list;
    list.insert(10);
    list.insert(20);
    list.insert(30);
    
    list.display();
    list.remove(20);
    list.display();
    
    return 0;
}

 


스택(Stack) 개념

  • LIFO(Last In First Out) 구조

  • push(삽입), pop(제거), top(최상단 요소 확인)

스택 구현 (C++)

#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> s;
    
    s.push(10);
    s.push(20);
    s.push(30);
    
    cout << "Top: " << s.top() << endl;
    
    s.pop();
    cout << "Top after pop: " << s.top() << endl;
    
    return 0;
}

 


큐(Queue) 개념

  • FIFO(First In First Out) 구조

  • push(삽입), pop(제거), front(첫 요소), back(마지막 요소)

큐 구현 (C++)

#include <iostream>
using namespace std;

class Queue {
private:
    struct Node {
        int data;
        Node* next;
        Node(int val) : data(val), next(nullptr) {}
    };

    Node *frontNode, *rearNode;

public:
    Queue() : frontNode(nullptr), rearNode(nullptr) {}

    void enqueue(int data) {
        Node* newNode = new Node(data);
        if (!rearNode) {
            frontNode = rearNode = newNode;
            return;
        }
        rearNode->next = newNode;
        rearNode = newNode;
    }

    void dequeue() {
        if (!frontNode) return;
        Node* temp = frontNode;
        frontNode = frontNode->next;
        if (!frontNode) rearNode = nullptr;
        delete temp;
    }

    int front() {
        return (frontNode) ? frontNode->data : -1;
    }

    bool isEmpty() {
        return frontNode == nullptr;
    }
};

int main() {
    Queue q;
    q.enqueue(10);
    q.enqueue(20);
    q.enqueue(30);
    
    cout << "Front: " << q.front() << endl;
    q.dequeue();
    cout << "Front after dequeue: " << q.front() << endl;
    
    return 0;
}

 


덱(Deque) 개념

  • 양방향 삽입/삭제 가능한 자료구조

  • push_front(), push_back(), pop_front(), pop_back() 제공

덱 구현 (C++)

#include <iostream>
using namespace std;

class Deque {
private:
    struct Node {
        int data;
        Node* next;
        Node* prev;
        Node(int val) : data(val), next(nullptr), prev(nullptr) {}
    };

    Node *frontNode, *rearNode;

public:
    Deque() : frontNode(nullptr), rearNode(nullptr) {}

    void push_front(int data) {
        Node* newNode = new Node(data);
        if (!frontNode) {
            frontNode = rearNode = newNode;
        } else {
            newNode->next = frontNode;
            frontNode->prev = newNode;
            frontNode = newNode;
        }
    }

    void push_back(int data) {
        Node* newNode = new Node(data);
        if (!rearNode) {
            frontNode = rearNode = newNode;
        } else {
            newNode->prev = rearNode;
            rearNode->next = newNode;
            rearNode = newNode;
        }
    }

    void pop_front() {
        if (!frontNode) return;
        Node* temp = frontNode;
        frontNode = frontNode->next;
        if (frontNode) frontNode->prev = nullptr;
        else rearNode = nullptr;
        delete temp;
    }

    void pop_back() {
        if (!rearNode) return;
        Node* temp = rearNode;
        rearNode = rearNode->prev;
        if (rearNode) rearNode->next = nullptr;
        else frontNode = nullptr;
        delete temp;
    }

    int front() {
        return (frontNode) ? frontNode->data : -1;
    }

    int back() {
        return (rearNode) ? rearNode->data : -1;
    }
};

int main() {
    Deque d;
    d.push_back(10);
    d.push_front(20);
    
    cout << "Front: " << d.front() << ", Back: " << d.back() << endl;
    
    d.pop_front();
    cout << "Front after pop: " << d.front() << endl;
    
    return 0;
}

 


해시 테이블(Hash Table) 개념

  • 키-값(Key-Value) 쌍으로 데이터를 저장하는 자료구조

  • 탐색 속도 O(1), 충돌 해결 방법 필요 (체이닝, 개방 주소법 등)

해시 테이블 구현 (C++)

#include <iostream>
#include <vector>
using namespace std;

class HashTable {
private:
    static const int SIZE = 10;
    vector<pair<int, int>> table[SIZE];

    int hashFunction(int key) {
        return key % SIZE;
    }

public:
    void insert(int key, int value) {
        int hashIndex = hashFunction(key);
        table[hashIndex].push_back({key, value});
    }

    int get(int key) {
        int hashIndex = hashFunction(key);
        for (auto &p : table[hashIndex]) {
            if (p.first == key) return p.second;
        }
        return -1; 
    }
};

int main() {
    HashTable ht;
    ht.insert(1, 100);
    ht.insert(11, 200);
    
    cout << "Key 1: " << ht.get(1) << endl;
    cout << "Key 11: " << ht.get(11) << endl;
    
    return 0;
}

 


셋(Set) 개념

  • 중복을 허용하지 않는 집합 자료구조

  • 삽입/삭제 O(log N) (Balanced BST 사용)

 

셋 구현 (C++)

#include <iostream>
using namespace std;

class Set {
private:
    struct Node {
        int data;
        Node* next;
        Node(int val) : data(val), next(nullptr) {}
    };

    Node* head;

public:
    Set() : head(nullptr) {}

    void insert(int data) {
        if (contains(data)) return;
        Node* newNode = new Node(data);
        newNode->next = head;
        head = newNode;
    }

    bool contains(int data) {
        Node* temp = head;
        while (temp) {
            if (temp->data == data) return true;
            temp = temp->next;
        }
        return false;
    }
};

int main() {
    Set s;
    s.insert(10);
    s.insert(20);
    s.insert(10); 
    
    return 0;
}

 

댓글을 작성해보세요.


채널톡 아이콘