데이터 구조 (Data Structure) 2

  • 순서가 없는(unordered) 데이터 구조
    • 세트(Set)
    • 딕셔너리(Dictionary)

 

세트 (Set)

Mutable, unordered, iterable

추가 및 삭제

  • .add(ele): elem을 세트에 추가합니다.

  • .update(*others): 여러가지 값(iterable)을 추가합니다.

    a = {'starbucks'}
    a.update({'hollys', 'tomntoms'}, ['tomntoms', 'gongcha'])
    # {'starbucks', 'hollys', 'tomntoms', 'gongcha'} 중복제거, 순서는 랜덤
  • .remove(elem): elem을 삭제하고, 없으면 KeyError가 발생합니다.

  • .discard(elem): elem을 삭제하고, 없어도 에러가 발생하지 않습니다.

  • .pop(): 임의의 원소를 제거하고 그 값을 반환합니다.

 

딕셔너리 (Dictionary)

Mutable, unordered, iterable

Key : Value 페어의 자료구조

조회

  • .get(key[, default]): key를 통해 value를 가져오며 절대 KeyError가 발생하지 않습니다. key가 없을 경우 그 키에 default값을 넣어 새로운 페어를 생성합니다.

    • default는 기본적으로 None입니다.
    my_dict = {'starbucks' : '카페', 'emart' : '마트', 'LGTWINS' : '프로야구구단'}
    print(my_dict['homeplus'])                # KeyError 발생
    print(my_dict.get('homeplus'))            # None 반환 (기본값이 None)
    print(my_dict.get('homeplus', '마트'))    # 마트 반환

추가 및 삭제

  • .pop(key[, default]): key가 딕셔너리에 있으면 제거 후 그 값을 반환합니다. 없을 경우 default값을 반환합니다.

    • 이 때, default값도 없을 경우 KeyError가 발생합니다.
  • .update(): 값을 제공하는 key, value로 덮어씁니다.

my_dict = {'starbucks' : '카페', 'emart' : '마트'}
my_dict.update(starbucks = '도서관')

딕셔너리 순회 (반복문 활용)

  • dictionary에서 for를 활용하는 4가지 방법

    1. key 활용
    2. .keys() 활용
    3. .values() 활용
    4. .items() 활용
    for key in dict:
        print(dict[key])
    
    for key in dict.keys():
        print(dict[key])
    
    for val in dict.values():
        print(val)
    
    for key, val in dict.items():
        print(key, val)

Dictionary comprehension

cubic = {x : x ** 3 for x in range(1, 5)}
print(cubic)        # {1 : 1, 2 : 8, 3 : 27, 4 : 64}

dusts = {'서울': 72, '대전': 82, '구미': 29, '광주': 45}
result = {x : '나쁨' if y > 80 else '보통' for x, y in dusts.items()}
print(result)        # {'서울': '보통', '대전': '나쁨', '구미': '보통', '광주': '보통'}

데이터 구조 (Data Structure) 1

Program = Data Sturcture + Algorithm -Niklaus Wirth

  • 순서가 있는(ordered) 데이터 구조
    • 문자열(String)
    • 리스트(List)
  • 데이터 구조에 적용 가능한 Built-in Function
    • map()
    • filter()

 

문자열 (String)

Immutable, ordered, iterable

조회 / 탐색

  • .find(x): x의 첫 번째 위치를 반환합니다. 값이 존재하지 않을 경우 -1을 반환합니다.
  • .index(x): x의 첫 번째 위치를 반환합니다. 값이 존재하지 않을 경우, 오류가 발생합니다.

값 변경

  • .replace(old, new[, count]): old의 문자열을 new의 문자열로 바꿔 반환합니다. count를 지정하면 그 횟수만큼만 시행합니다.

  • .strip([chars]): 특정한 문자를 제거합니다.

    '    oh!\n'.strip()            # 특정 문자 지정없으면 공백 제거 -> oh!
    '    oh!\n    '.lstrip()        # 'oh!\n    ' 왼쪽만 제거
    'hehehihihihi'.rstrip('hi')        # 'hehe' 오른쪽만 제거
  • .split(): 문자열을 특정 단위로 나누어 리스트로 반환합니다.

  • 'separator'.join(iterable): separator를 구분자로 합쳐 한 문자열로 반환합니다.

문자 변형

원본 자체를 변형시키는 것이 아님!

  • .capitalize(): 맨 앞글자를 대문자로 바꿔 반환
  • .title(): 공백이나 ''이후를 대문자로 바꿔 반환
  • .upper(): 문자열 전체를 대문자로 바꿔 반환
a = 'this is my student\'s call'

a.capitalize()        # "This is my student's call"
a.title()            # "This Is My Student'S Call"
a.upper()            # "THIS IS MY STUDENT'S CALL"
  • .lower(): 문자열 전체를 소문자로 바꿔 반환
  • .swapcase(): 문자열의 대소문자를 서로 바꿔 반환
  • 문자열 검증 메소드 (참 / 거짓 반환): .isalpha(), .isdecimal(), .isdigit(), .isnumeric(), .isspace(), .isupper(), .istitle(), .islower()

 

리스트 (List)

Mutable, ordered, iterable

값 추가 및 삭제

  • .append(x): 리스트 맨 뒤에 값을 추가합니다.
  • .extend(iterable): 리스트에 iterable(list, range, tuple, string) 값을 붙일 수 있습니다.
cafe = ['starbucks']            # ['starbucks']
cafe.append(['hollys'])            # ['starbucks', ['hollys']]
cafe.extend(['tomntoms'])        # ['starbucks', ['hollys'], 'tomntoms']
cafe.append('gongcha')            # ['starbucks', ['hollys'], 'tomntoms',                                         'gongcha']
cafe.extend('ediya')            # ['starbucks', ['hollys'], 'tomntoms',                                         'gongcha', 'e', 'd', 'i', 'y', 'a']
  • .insert(i, x): i번째 위치에 x를 추가합니다.
    • i가 리스트의 길이를 넘어설 때는 리스트 맨 뒤에 원소를 추가합니다.
  • .remove(x): 리스트에서 값이 x인 것을 삭제합니다. 값이 없을 경우 오류가 발생합니다.
  • .pop(i): i번째 위치의 값을 삭제하고 반환합니다. i가 없을 경우 맨 뒤의 항목으로 대신합니다.
  • .clear(): 빈 리스트로 초기화합니다.

탐색 및 정렬

  • .index(x): x값의 index를 반환합니다. 값이 없을 경우 오류가 발생합니다.

  • .count(x): x값의 개수를 반환합니다.

  • .sort(): sorted()와 달리 원본 list를 변형시키고, None을 리턴합니다

  • .reverse(): 반대로 뒤집습니다. (정렬 아님!)

    a = ['starbucks', 'hollys', 'tomntoms']
    a.reverse()        # 이대로 출력하면 None return
    print(a)        # ['tomntoms', 'hollys', 'starbucks']

리스트 복사

  • copy_list = original_list 등으로 복사하면 절대 안됨! (참조값이 복사되어 둘다 원본이 되어버림)

얕은 복사 (shallow copy)

  1. slice 연산자 사용 [:]

    a = [1, 2, 3]
    b = a[:]
  2. list() 활용

    a = [1, 2, 3]
    b = list(a)

깊은 복사 (deep copy)

import copy
a = [1, 2, [1, 2]]
b = copy.deepcopy(a)

List Comprehension

표현식과 제어문을 통해 리스트를 생성합니다. 여러 줄의 코드를 한 줄로 줄일 수 있습니다.

even_list = [i for i in range(1, 11) if i % 2 == 0]
print(even_list) = [2, 4, 6, 8, 10]

# 1부터 50 사이의 자연수 중 피타고라스 방정식 만족하는 수 찾기
result = [(x, y, z) for x in range(1, 50) for y in range(x + 1, 50) for z in range(y + 1, 50) if z * z == x * x + y * y]

# 모음 제거하기
result = [word for word in words if word not in vowels]
  • elif는 if else문의 중첩으로 써야 합니다.
    • [식 if 조건식 else 식 if ... else ... for 변수 in iterable]

 

데이터 구조에 적용가능한 Built-in Function

iterable 데이터 구조에 적용가능한 Built-in Function

iterable: list, dict, set, str, bytes, tuple, range

  • map(function, iterable)

    • iterable 데이터 구조의 모든 요소에 function 적용 후 map_object형태로 반환합니다.
    # function으로 사용자 정의 함수도 쓸 수 있음
    new_numbers = list(map(cube, numbers))        # cube(n)은 세제곱 사용자 정의 함수
  • filter(function, iterable)

    • iterable 데이터 구조에서 function 반환값이 True인 것만 filter object로 반환합니다.
    new_numbers = list(filter(odd, numbers))    # odd(n)은 홀수면 참 반환하는 함수
    new_numbers = [number for number in numbers if number % 2]        # 동일 값 반환
  • zip(*iterables)

    • 복수의 iterable 객체를 모아 튜플의 모음으로 구성된 zip object로 반환합니다.
    drinks = ['beer', 'wine', 'soju']
    foods = ['chicken', 'pasta', 'pork']
    pair = list(zip(drinks, foods))        # [('beer, chicken'), ('wine', 'pasta'),                                     ('soju, pork')]
  • reduce(function, iterable[, initializer])

    • 인자가 두 개인 function을 왼쪽에서 오른쪽으로 iterable 항목에 누적으로 적용하여 단일 값으로 줄입니다.
    from functools import reduce
    reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])        # ((((1 + 2) + 3) + 4) + 5)

에러 (Error)

 

문법 에러 (Syntax Error)

문법 에러가 있는 프로그램은 실행되지 않습니다.

  • 에러 발생 시 SyntaxError라는 키워드와 에러 상세 내용을 보여줍니다.
  • 파일이름줄번호, ^ 문자를 통해 파이썬이 코드를 읽어들일 때(parser) 문제가 발생한 위치를 표시합니다.
    • parser는 줄에서 에러가 감지된 가장 앞의 위치를 가리키는 '^'를 표시합니다.
    • 정확한 위치를 지정하지 않을 때도 있으므로 지정된 위치 전후를 모두 확인해야 합니다.
# EOL (End of Line Error)
print('hi)

# EOF (End of File Error)
print('hi'

 

예외 (Exception)

문법적으로는 문제가 없지만, 실행시 발생하는 에러입니다.

  • 모든 에러는 Exception을 상속받아 이뤄집니다.
# ZeroDivisionError (0으로 나눌 경우)
1 / 0

# NameError (정의되지 않은 변수 호출)
print(me)

# TypeError (1: 맞지 않는 타입끼리 연산 등 동작 실행)
1 + '1'

# TypeError (2: 함수 잘못 호출 - 인자 개수 초과 / 미만 등)
round('3.5')    # 함수에 지원하지 않는 타입 넣기

# ValueError (1: 존재하지 않는 값 찾을 때)
numbers = [1, 2]
numbers.index(3)

# ValueError (2: 타입은 맞으나 값이 적절하지 않을 경우)
int('3.5')

# IndexError (존재하지 않는 idx 찾을 때)
mylist = []
mylist[-1]

# KeyError (존재하지 않는 key를 호출)
mydic = {'아침밥': '계란'}
mydic['점심밥']

# ModuleNotFoundError (모듈이 없는 경우)
import mymodule

# ImportError (모듈은 있지만 모듈 내 클래스 등을 가져올 때 오류)
from random import sam

# KeyboardInterrupt (무한루프 등에서 사용자가 직접 프로그램을 중지하는 경우)
while True:
    continue    # 무한루프 -> 사용자가 ctrl + c로 탈출하면 keboardinterrupt 발생

 

예외 처리 (Exception Handling)

try&except

try문을 사용하여 예외 처리를 할 수 있습니다.

try:
    num = int(input('값을 입력하세요: '))
    print(num)
except:
    print('숫자를 입력해주세요.')

에러 메세지 (as)

as 키워드를 활용하여 에러 메세지를 보여줄 수 있습니다.

try:
    mylist = []
    print(mylist[-1])
except IndexError as error:        # 에러메세지를 error 변수에 저장
    print(error)

복수의 예외 처리

  • 괄호가 있는 튜플로 여러 개의 예외를 지정할 수 있습니다.
try:
    mylist = []
    print(mylist[-1])
except (IndexError, ValueError):
    print('에러가 발생했습니다.')
  • 혹은 각각 다른 오류 메세지를 출력할 수 있습니다.
    • 이 때 가장 작은 범위의 에러부터 순차적으로 걸리기 때문에 순서에 유의해야 합니다.
try:
    mylist = []
    print(mylist[-1])
except Exception:        # 가장 큰 범위
    print('에러 발생')
except IndexError:
    print('올바른 범위를 입력해주세요.')
except ValueError:
    print('적절한 값을 입력해주세요.')

else

에러가 발생하지 않는 경우 실행시킬 문장에 사용되기 때문에 except 코드 뒤에 와야 합니다.

finally

예외의 발생 여부와 관계없이 항상 실행되는 코드입니다.

 

예외 발생시키기 (Exception Raising)

raise

raise를 통해 사용자가 지정한 예외를 강제로 발생시킬 수 있습니다. (항상 발생!)

raise NameError('이름이 없습니다.')        # 오류 발생

def mydiv(n1, n2):
    try:
        n1 / n2
        raise ValueError
    except ZeroDivisionError:
        print('division by zero 오류가 발생하였습니다.')
    except TypeError:
        print('숫자를 넣어주세요.')
    else:
        return n1 / n2

mydiv(1, 0)                # division by zero 오류가 발생하였습니다.
mydiv('1', '2')            # 숫자를 넣어주세요.
mydiv(1, 5)                # ValueError 발생 (올바른 값이어도 항상 발생)

assert

상태를 검증하는데 사용되며 검증식이 거짓일 경우 항상 AssertionError가 발생합니다.

# assert 뒤의 boolean이 거짓일 경우 에러 메세지 출력
def mydiv2(n1, n2):
    assert type(1) == int, '숫자가 아닙니다.'
    print(n1 // n2, n1 % n2)

mydiv2(1, 2)            # 0 1
mydiv2('1', '2')        # AssertionError 발생

Function 2

함수와 스코프 (scope)

함수는 코드 내부에 지역 스코프(local scope)를 생성합니다.

  • 전역 스코프 (global scope) / 전역 변수 (local variable): 코드 어디에서든 참조할 수 있는 공간/변수
  • 지역 스코프 (local scope) / 지역 변수 (local variable): 함수 내부에서만 참조할 수 있는 공간/변수
  • 전역 변수는 어디서든 참조 가능하지만, 전역에서 지역 변수를 호출할 수는 없습니다.
    • 전역 변수를 지역 스코프에서 바꾸고자 할 경우 global선언을 활용할 수 있습니다.
global_num = 3
def local_scope():
    global global_num                # 전역 변수 가져오기
    global_num = 5                    # 변경
    return f'global_num이 {global_num}으로 설정되었습니다.'

print(local_scope())                # global_num이 5으로 설정되었습니다.
print('global_num:', global_num)    # global_num: 5

이름 검색 (resolution) 규칙

파이썬에서 사용되는 식별자들은 namespace에 저장되어 있습니다. 이름들은 LEGB Rule에 따라 검색합니다.

  • Local scope: 정의된 함수
  • Enclosed scope: 상위 함수
  • Global scope: 함수 밖의 변수 혹은 import된 모듈
  • Built-in scope: 파이썬안에 내장되어 있는 함수 또는 속성

변수의 수명주기 (lifecycle)

  • 빌트인 스코프(built-in scope): 파이썬이 실행된 이후부터 영원히 유지
  • 전역 스코프(global scope): 모듈이 호출된 시점/이름 선언된 이후부터 인터프리터가 끝날때까지 유지
  • 지역(함수) 스코프(local scope): 함수가 호출될 때 생성되고, 함수가 종료/처리되지 않는 예외를 일으킬 때 삭제

 

재귀 함수 (recursive function)

재귀 함수는 함수 내부에서 자기 자신을 호출하는 함수를 뜻합니다.

팩토리얼 계산

  1. 반복문을 이용한 팩토리얼 계산
def fact(n):
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result
print(fact(5))                    # 120
  1. 재귀를 이용한 팩토리얼 계산
def factorial(n):
    if n == 1:
        return 1
    return n * factorial(n - 1)
print(factorial(5))                # 120

피보나치 수열

  1. 반복문을 이용한 피보나치 수열 계산
def fib_loop(n):
    fibo = [0, 1, 1]
    for i in range(3, n + 1):
        fibo.append(fibo[i - 1] + fibo[i - 2])
    return fibo[n]
print(fib_loop(10))                # 55
  1. 재귀를 이용한 피보나치 수열 계산
def fib(n):
    if n == 1 or n == 2:
        return 1
    return fib(n - 1) + fib(n - 2)
print(fib(10))                    # 55

최대 재귀 깊이

끝없이 재귀 함수를 호출할 경우 RecursionError가 발생합니다. 파이썬에서는 최대 재귀 깊이(maximum recursion depth)가 1,000으로 정해져 있기 때문입니다.

반복문과 재귀 함수의 차이

두 코드 모두 원리는 같습니다!

  • 재귀 호출은 변수 사용을 줄일 수 있습니다.
  • 재귀함수는 기본적으로 같은 문제를 점점 적은 범위로 줄여서 푸는 방식입니다.
  • 재귀함수를 작성할 때는 반드시 base case를 지정해 주어야 합니다. (더 이상 반복되지 않는 지점)
  • 코드가 더 직관적이고 이해하기 쉬운 경우가 있습니다.
    • 그러나 대부분의 재귀함수 풀이는 반복문보다 느립니다.

Function 1

 

함수 (Function)

특정한 기능(function)을 하는 코드의 묶음

 

함수를 쓰는 이유

  • 가독성
  • 재사용성
  • 유지보수

 

함수의 선언과 호출

  • def로 시작하여 :로 끝나고, 코드블록을 추가합니다.
  • return값이 없으면 None값을 반환합니다.
# 실수하기 쉬운 것들
result = print('hi')    # hi 출력
type(result)            # NoneType 출력

sorted_list = [5, 2, 3, 4, 1].sort()
print(sorted_list)        # None 출력
  • 내장함수(built-in-functions)
dir(__builtins__)        # built in 함수 출력하는 명령어

 

함수의 Output

함수의 return
  • 함수는 반환값이 있으며, 이는 어떠한 것이라도 상관없지만 단 하나의 객체만 반환됩니다.
  • 함수가 return되거나 종료되면, 함수를 호출한 곳으로 돌아갑니다.

 

함수의 입력 (Input)

  • 매개변수 (parameter): 함수 정의 단계에서 입력을 받아 함수 내부에서 활용할 변수
  • 인자 (argument): 함수 호출 단계에서 실제로 전달되는 입력값
 
함수의 인자

함수는 입력값(input)으로 인자(argument)를 넘겨줄 수 있습니다.

  • 위치 인자 (Positional Arguments): 함수는 기본적으로 인자를 위치로 판단합니다.
  • 기본 인자 값 (Default Argument Values): 함수가 호출될 때, 인자를 지정하지 않아도 기본 값을 설정할 수 있습니다.
    • 단, 기본 인자값을 가지는 인자 다음에 기본 값이 없는 인자를 사용할 수 없습니다.
def greeting(name = '익명'):
    return (f'{name}, 안녕?')
print(greeting())                # 익명, 안녕?
print(greeting('하영'))            # 하영, 안녕?
  • 키워드 인자 (Keyword Arguments): 직접 변수의 이름으로 특정 인자를 전달합니다.
    • 단, 키워드 인자를 활용한 다음에 위치 인자를 활용할 수 없습니다.
    • 전부 키워드 표시 하거나, 전부 안 하거나, 제일 끝에만 하거나!
def greeting(age, name = '익명'):
    return f'{age}세 {name}님 환영합니다.'
greeting(name = '홍길동', 20)        # SyntaxError 발생

 

정해지지 않은 여러 개의 인자 처리

print()함수도 내장함수 코드를 살펴보면 인자에 *가 붙어있습니다.

가변 (임의) 인자 리스트 (Arbitrary Argument Lists)

가변 인자 리스트는 tuple형태로 처리가 되며, 매개변수에 *로 표현합니다.(*args) eg) print()

가변 (임의) 키워드 인자 (Arbitrary Keyword Arguments)

정해지지 않은 키워드 인자들은 dict형태로 처리가 되며, **로 표현합니다.(**kwargs) eg)dict()

def my_dict(**kwargs):
    return kwargs
my_dict(한국어 = '안녕')                # {'한국어': '안녕'}
# return 타입은 dict
type(my_dict(한국어 = '안녕'))        # dict

큐 (Queue)

이 정리는 위키백과를 참고하였습니다.

  • FIFO: 선입선출(First In First Out), 제일 먼저 들어간 것이 제일 먼저 나간다는 뜻입니다.
    • 예시: 카페 주문, 선입선출 물건 판매 (유통기한)
  • 큐는 양 쪽 끝에서 자료를 넣거나 뺄 수 있는 선형의 자료 구조입니다.
    • 하지만 한 쪽(rear)에서는 삽입만, 반대쪽(front)에서는 삭제만 일어납니다.
  • 맨 처음에 들어온 데이터의 위치를 front (혹은 first)이라고 합니다.
  • 큐는 그래프 자료구조 탐색방법 중 BFS(Breath First Search, 깊이우선 탐색)에 쓰입니다.
  • 그 외에 CPU 스케쥴링 등의 프로세스, 자원을 공유하는 대부분의 경우에 큐가 사용됩니다.
  • 기본적으로 추상 자료형(Abstract Data Type, ADT)이지만 여기서는 자료 구조의 영역까지 다룰 것입니다. (구현까지)

 

구현 방법 - Stack과 동일

  1. 1차원 배열: 구현하기 쉽지만 input의 개수를 알아야 합니다.
  2. 연결 리스트: 구현이 배열보다 어렵고 메모리를 좀 더 사용하지만, 유동적으로 input에 대처할 수 있습니다.

 

함수

가장 보편적으로 사용되는 함수를 골라보았습니다. 이외에 size()등의 함수들도 사용자가 정의하여 쓸 수 있습니다.

  • Q.front(): 큐의 가장 앞 데이터(front)를 반환합니다.
  • Q.deque(): first을 반환하고 스택에서 삭제합니다.
  • Q.enque(): 큐의 끝에(rear) 새로운 데이터를 삽입합니다.
  • Q.isEmpty(): 큐가 비었으면 True, 아니면 False을 반환합니다.

 

큐 구현 코드 (Python, C++)

  • Python: 큐 라이브러리가 따로 존재하지만 list를 이용하여 구현해 보았습니다.
    • 파이썬에서는 리스트에서 remove를 할 때마다 자동으로 인덱스가 조정되기 때문에 항상 0 위치의 원소를 deque하거나 front할 때 사용했습니다.
class queue:
    def __init__(self):
        self.items = []
    def enque(self, item):
        self.items.append(item)
    def deque(self):
        tmp = self.items[0]                        # 첫 번째 원소 tmp에 저장
        self.items.remove(tmp)                    # item에서 삭제
        return tmp                                # tmp 반환
    def isEmpty(self):
        return not self.items
    def front(self):
        return self.items[0]                    # 첫 번째 원소 반환

q = queue()
print(q.isEmpty())                                # True 출력
q.enque(1)
q.enque(2)
print(q.deque())                                # 1 출력
q.enque(3)
print(q.front())                                # 2 출력
print(q.isEmpty())                                # False 출력
  • C++: 노드를 이용한 연결리스트로 스택을 구현해 보았습니다.
#include <iostream>

using namespace std;

struct Node {
    int data;
    Node* next;
    Node() {
        next = NULL;
        data = 0;
    }

    Node(int i, Node* ptr) {
        data = i;
        next = ptr->next;
        ptr->next = this;
    }
};

struct Queue {
    Node* first;
    Node* rear;                                // 큐에는 맨 뒤를 가리키는 포인터 필요
    int count;
    Queue() {
        first = new Node();
        rear = new Node();                    // 둘 다 next값을 NULL로 초기화
        count = 0;
    }

    int deque() {
        if (count != 0) {
            int res = first->data;
            first = first->next;
            count--;
            return res;
        }
    }

    int front() {
        if (count != 0) {
            return first->data;
        }
    }

    bool isEmpty() {
        if (count == 0) {
            return true;
        }
        else return false;
    }

    void enque(int data) {                    // 스택과 다른 삽입과정
        Node* node = new Node();
        node->data = data;
        node->next = NULL;                    // 삽입될 노드의 next값을 NULL로 설정
        if (count == 0) {                    // 첫 숫자일 때 첫 번째 노드로 설정
            first = node;
        }
        else {                                // 기존 rear의 next값을 현 node로 갱신
            rear->next = node;
        }
        rear = node;                        // 맨 마지막을 node로 갱신(공통)
        count++;
    }
};

int main() {
    Queue* q = new Queue();
    cout << q->isEmpty() << '\n';            // 1 출력
    q->enque(1);
    q->enque(2);
    cout << q->deque() << '\n';                // 1 출력
    q->enque(3);
    cout << q->front() << '\n';                // 2 출력
    cout << q->isEmpty() << '\n';            // 0 출력
}

 

사담

오랜만에 자료구조를 보는데 C++로 노드랑 링크드 리스트 구현을 하는 게 너무 새롭네요..

그 때는 주먹구구 암기식으로 외웠던 것 같은데 포스팅의 장점은 정말 이해하려고 노력하게 만든다는 점 같아요🙌🙌

직접 구현해보는 게 중요하다는 말이 뭔지 이제야 알 것 같습니다!!

'자료구조' 카테고리의 다른 글

자료구조: 스택(Stack)  (0) 2020.07.26
자료구조: 배열(Array)와 리스트(List)  (0) 2020.07.24

+ Recent posts