[알고리즘 특강]자료구조/알고리즘 특강 요약 2일차

선형 자료구조(1일차에 이어서)

5) 큐(Queue)

큐 구현(개선)

전역

SIZE = 5
queue = [None for _ in range(SIZE)] # list_comprehension으로 queue  생성
front = rear = -1

함수

def isQueueFull(): # 큐가 꽉찼는지 확인하는 함수
    global SIZE, queue, front, rear
    if (rear != SIZE-1):
        return False
    elif (rear == SIZE-1 and front == -1): # front가 출구 끝이면
        return True
    else:
        for i in range(front+1, SIZE) :  
            queue[i-1]  = queue[i]
            queue[i] = None
        front -= 1
        rear -= 1
        return False
    # 출구 쪽 None 공간으로 남은 값들을 밀어줘 새로운 값이 들어갈 수 있도록 해줌
    
    
def isQueueEmpty(): # 큐가 비었는지 확인하는 함수
    global SIZE, queue, front, rear
    if (rear == front):
        return True
    else:
        return False
    
    
def enQueue(data): # 큐에 데이터를 넣는 함수
    global SIZE, queue, front, rear
    if (isQueueFull()):
        print('큐가 꽉 찼습니다.')
        return
    rear += 1
    queue[rear] = data
    


def deQueue(): # 큐에서 데이터를 빼는 함수
    global SIZE, queue, front, rear
    if isQueueEmpty():
        print('큐가 비었습니다.')
        return None
    front += 1
    data = queue[front]
    queue[front] = None
    return data


def peek(): # 다음 나올 데이터를 알려주는 함수
    global SIZE, queue, front, rear
    if isQueueEmpty():
        print('큐가 비었습니다.')
        return None
    return queue[front+1]

메인

enQueue('화사')
enQueue('솔라')
enQueue('문별')
enQueue('선미')
enQueue('동준')
print('출구<-----',queue,'<-----입구')
print('밥 손님 : ', deQueue())
print('밥 손님 : ', deQueue())
print(queue) # 출구쪽 공간 0과 1이 None
enQueue('아이유')  # 아이유가 들어갈 수 있도록 앞의 값들의 위치가 1씩 줄어듬
print('출구<-----',queue,'<-----입구')
출구<----- ['화사', '솔라', '문별', '선미', '동준'] <-----입구
밥 손님 :  화사
밥 손님 :  솔라
[None, None, '문별', '선미', '동준']
출구<----- [None, '문별', '선미', '동준', '아이유'] <-----입구

6) 원형 큐

원형 큐란?

  • 큐의 처음과 끝이 연결된 구조

차이점

  1. 순차 큐에서는 오버헤드가 발생하지만 원형 큐는 처음과 끝이 연결되어 있어 오버헤드가 발생하지 않는다.
  2. 큐가 꽉찬 상태이지만 front가 rear보다 크게 되었을 때 비었다고 인식할 수 있다. 그래서 % 큐의크기 를 사용해 그 점을 방지하는 것이 원형 큐다.

원형 큐 구현

전역

SIZE = 5
queue = [None for _ in range(SIZE)] # list_comprehension으로 queue  생성
front = rear = -1

함수

def isQueueEmpty(): # 큐가 비었는지 확인하는 함수
    global SIZE, queue, front, rear
    if (rear == front):
        return True
    else:
        return False

def isQueueFull(): # 큐가 꽉찼는지 확인하는 함수
    global SIZE, queue, front, rear
    if ((rear+1) % SIZE == front):
        return True
    else:
        return False

    
def enQueue(data): # 큐에 데이터를 넣는 함수
    global SIZE, queue, front, rear
    if (isQueueFull()):
        print('큐가 꽉 찼습니다.')
        return
    rear = (rear + 1) % SIZE
    queue[rear] = data
    

def deQueue(): # 큐에서 데이터를 빼는 함수
    global SIZE, queue, front, rear
    if isQueueEmpty():
        print('큐가 비었습니다.')
        return None
    front = (front+1) % SIZE
    data = queue[front]
    queue[front] = None
    return data


def peek(): # 다음 나올 데이터를 알려주는 함수
    global SIZE, queue, front, rear
    if isQueueEmpty():
        print('큐가 비었습니다.')
        return None
    return queue[(front+1) % SIZE]

메인

enQueue('화사')
enQueue('솔라')
enQueue('문별')
enQueue('선미')
enQueue('동준')
print(queue)
print('밥 손님 : ', deQueue())
print('밥 손님 : ', deQueue())
print(queue)
enQueue('아이유') 
print(queue)
print('밥 손님 : ', deQueue())
enQueue('박진영')
print(queue)
print('밥 손님 : ', deQueue())
enQueue('백종원')
print(queue)
print('밥 손님 : ', deQueue())
print('밥 손님 : ', deQueue())
enQueue('유재석')
print(queue)
['화사', '솔라', '문별', '선미', '동준']
밥 손님 :  화사
밥 손님 :  솔라
[None, None, '문별', '선미', '동준']
['아이유', None, '문별', '선미', '동준']
밥 손님 :  문별
['아이유', '박진영', None, '선미', '동준']
밥 손님 :  선미
['아이유', '박진영', '백종원', None, '동준']
밥 손님 :  동준
밥 손님 :  아이유
[None, '박진영', '백종원', '유재석', None]


비선형 자료구조

1) 이진 트리

트리구조란?

  • 회사 사장을 필두로 그 아래 직책들이 구성되어 있는 조직표 또는 컴퓨터 상위 폴더 안에 하위 폴더들이 계속 이어져 있는 구조와 같은 구성

이진 트리의 종류

  • 포화 이진 트리, 완전 이진 트리, 편향 이진 트리 등

이진 트리의 순회

  • 순회 종류
    • 이진 트리의 노드 전체를 한 번씩 방문하는 것을 순회(traversal)라고 함
    • 노드 데이터를 처리하는 순서에 따라 전위 순회, 중위 순회, 후위 순회
  1. 전위 순회(preorder traversal)
    1. 현재 노드 데이터 처리
    2. 왼쪽 서브 트리로 이동
    3. 오른쪽 서브 트리로 이동
  2. 중위 순회(inorder traversal)
    1. 왼쪽 서브 트리로 이동
    2. 현재 노드 데이터 처리
    3. 오른쪽 서브트리로 이동
  3. 후위 순회(postorder traversal)
    1. 왼쪽 서브 트리로 이동
    2. 오른쪽 서브 트리로 이동
    3. 현재 노드 데이터 처리

이진트리구현

전역


함수

class TreeNode():
    def __init__(self):
        self.left = None
        self.data = None
        self.right = None

메인

node1 = TreeNode()
node1.data = '화사'

node2 = TreeNode()
node2.data = '솔라'
node1.left = node2

node3 = TreeNode()
node3.data = '문별'
node1.right = node3

node4 = TreeNode()
node4.data = '휘인'
node2.left = node4

node5 = TreeNode()
node5.data = '쯔위'
node2.right = node5

node6 = TreeNode()
node6.data = '선미'
node3.left = node6

print(node1.data)
print(node1.left.data, node1.right.data)
print(node1.left.left.data, node1.left.right.data, node1.right.left.data)
화사
솔라 문별
휘인 쯔위 선미

2) 이진 탐색 트리

이진 탐색 트리의 특징

  • 이진 트리 중 활용도가 높은 트리로, 데이터 크기를 기준으로 일정 형태로 구성함
  1. 왼쪽 서브 트리는 루트 노드보다 모두 작은 값을 가진다.
  2. 오른쪽 서브 트리는 루트 노드보다 모두 큰 값을 가진다.
  3. 각 서브 트리도 1,2의 특징을 갖는다.
  4. 모든 노드 값은 중복되지 않는다. 즉, 중복된 값은 이진 탐색 트리에 저장할 수 없다.

이진 탐색 트리 구현

전역

memory = []
root = None
nameAry = ['블랙핑크','레드벨벳','마마무','에이핑크','트와이스']

함수

class TreeNode():
    def __init__(self):
        self.left = None
        self.data = None
        self.right = None

메인

# 첫 노드 생성
node = TreeNode()
node.data = nameAry[0]
root = node
memory.append(node)

for name in nameAry[1:]: # 레드벨벳부터
    node = TreeNode()
    node.data = name
    
    current = root
    while True:
        if name < current.data :
            if current.left == None:
                current.left = node
                break
            current = current.left
        else:
            if current.right == None:
                current.right = node
                break
            current = current.right
    
    memory.append(node)
print('이진 탐색트리 완료!')
이진 탐색트리 완료!
findData = '마마무'

current = root
while True:
    if current.data == findData :
        print(findData, '찾음^^')
        break
    elif current.data > findData:
        if current.left == None:
            print(findData, '이 트리에 없음')
            break
        current = current.left
    else:
        if current.right == None:
            print(findData, '이 트리에 없음')
            break
        current = current.right
        

마마무 찾음^^

3) 그래프

그래프 구조란?

  • 버스 정류장과 여러 노선이 함께 포함된 형태 또는, 링크드인(Linked in)과 같은 사회 관계망 서비스의 연결 등의 형태

그래프의 개념

  • 여러 노드가 서로 연결된 자료구조
  • 예) 지하철 노선도, 도시 도로망, 전기 회로도, 인맥 관계도

그래프의 종류

  1. 무방향 그래프
    • 간선(Edge)에 방향성이 없는 그래프
  2. 방향 그래프
    • 화살표로 간선 방향을 표기하고, 그래프의 정점 집합이 무방향 그래프와 같음
  3. 가중치 그래프
    • 간선마다 가중치가 다르게 부여된 그래프
    • 무방향 그래프와 방향 그래프에 각각 가중치를 부여한 경우

깊이 우선 탐색의 작동

  • 그래프의 모든 정점을 한 번씩 방문하는 것을 그래프 순회(Graph Traversal)라고 함
  • 그래프 순회 방식은 깊이 우선 탐색, 너비 우선 탐색이 대표적

그래프의 인접 행렬 표현

  • 그래프를 코드로 구현할 때는 인접 행렬을 사용
  • 인접 행렬은 정방향으로 구성된 행렬로 정점이 4개인 그래프는 4x4로 표현
  • 인접 행렬은 대각선으로 대칭

함수

class Graph():
    def __init__(self, size): # size = 정점의 개수
        self.SIZE = size
        self.graph = [ [0 for _ in range(size)] for _ in range(size)]
        

전역

G = None

메인

G = Graph(4)
G.graph[0][1] = 1; G.graph[0][2] = 1; G.graph[0][3] = 1
G.graph[1][0] = 1; G.graph[0][2] = 1;
G.graph[2][0] = 1; G.graph[2][1] = 1; G.graph[2][3] = 1
G.graph[3][0] = 1; G.graph[3][2] = 1


for row in range(4):
    for col in range(4):
        print(G.graph[row][col], end = '  ')
    print()
0  1  1  1  
1  0  0  0  
1  1  0  1  
1  0  1  0  


알고리즘

  • 어떤 문제를 해결해 가는 논리적인 과정
  • 자료구조라는 재료로 요리를 하는 과정이 알고리즘

알고리즘 표현법

  • 일반 언어 표현
    • 일반적인 자연어를 사용해서 설명하듯이 알고리즘을 표현
    • 일반 사람이 이해하기 쉽게 표현할 수 있으나, 최종적으로 코드로 변경하는 데는 한계가 있음.
    • 어떤 알고리즘을 사용해야 할지 아이디어가 떠오르지 않는 시점에서, 생각 범위를 넓히는 단계 정도에 사용하면 무난
  • 순서도를 이용한 표현
    • 여러 종류의 상자와 상자를 이어 주는 화살표를 이용해서 명령 순서를 표현
    • 간단한 알고리즘은 쉽게 표현할 수 있지만, 복잡한 알고리즘은 표현하기 어려운 경우가 많음
  • 의사코드를 이용한 표현
    • 프로그래밍 언어보다는 좀 더 인간의 언어에 가까운 형태
    • 프로그램 코드와 일반언어의 중간
    • 프로그램 코드를 코딩하는 것보다 알고리즘을 좀 더 명확히 정립하는데 도움이 되고 코드에 설명을 달지 않아도 이해하는 데 무리가 없다.
  • 프로그램 코드로 표현
    • 실제로 사용하는 프로그래밍 언어의 코드로 바로 작성 가능
  • 혼합 형태
    • 간단한 알고리즘은 직접 코드로 작성
    • 복잡한 알고리즘은 일반 언어, 의사코드, 순서도, 그림 등을 종합적으로 활용해서 표현

알고리즘의 성능

  • 알고리즘의 성능 측정
    • 알고리즘을 소요 시간을 기준으로 알고리즘 성능을 분석 방법이 ‘시간 복잡도(Time Complexity)
  • 알고리즘 성능 표기
    • 빅-오 표기법(Big-Oh Notation)으로 O(f(n)) 형태
    • 대표적인 함수는 O(1), O(log n), O(n), O(n log n) 등이 있다.

1) 정렬

정렬의 개념

  • 중요 알고리즘 중 하나인 정렬(sort)은 자료들을 일정한 순서대로 나열한 것
  • 예) 학교 출석부 또는 종류에 따라 가지런히 놓여 있는 칼들처럼 순서대로 데이터가 나열되어 잇는 것

정렬 알고리즘의 종류

  • 오름차순 정렬이든 내림차순 정렬이든 결과의 형태만 다를 뿐이지 같은 방식으로 처리됨
  • 정렬하는 방법에 대한 정렬
    • 선택 정렬(Selection Sort)
    • 삽입 정렬(Selection Sort)
    • 버블 정렬(Bubble Sort)
    • 퀵 정렬(Quick Sort)

선택정렬

선택 정렬의 개념

  • 여러 데이터 중에서 가장 작은 값을 뽑는 작동을 반복하여 값을 정렬

선택 정렬 구현 1

함수
def findMinIndex(ary) : # 최소값의 위치를 찾는 함수
    minIdx = 0
    for i in range(1, len(ary)):
        if (ary[minIdx] > ary[i]):
            minIdx = i
    return minIdx
전역
# testAry = [55, 88, 33, 77]
import random
testAry = [ random.randint(0,99) for _ in range(20)]
메인
print(testAry)
minPos = findMinIndex(testAry)
print('최솟값', testAry[minPos])
[30, 68, 32, 38, 7, 20, 98, 13, 67, 19, 81, 48, 59, 52, 19, 30, 57, 70, 31, 90]
최솟값 7

선택 정렬 구현 2(방 두개를 씀)

전역
import random
before = [ random.randint(100, 200) for _ in range(10)]
after = []
함수
def findMinIndex(ary) :
    minIdx = 0
    for i in range(1, len(ary)):
        if (ary[minIdx] > ary[i]):
            minIdx = i
    return minIdx
메인
print('정렬 전 -->', before)
for _ in range(len(before)):
    minPos = findMinIndex(before)
    after.append(before[minPos])
    del(before[minPos])
print('정렬 후 -->', after)
정렬 전 --> [142, 196, 193, 177, 138, 105, 102, 127, 173, 194]
정렬 후 --> [102, 105, 127, 138, 142, 173, 177, 193, 194, 196]

선택 정렬 구현 3(방 한개를 씀)

전역
import random
dataAry = [random.randint(100,200) for _ in range(10)]
함수
def selectionSort(ary):
    n = len(ary)
    for cy in range(0, n-1):
        minIdx = cy
        for i in range(cy+1, n):
            if (ary[minIdx] > ary[i]):
                minIdx = i
        ary[cy], ary[minIdx] = ary[minIdx], ary[cy]
    return ary
메인
print('정렬 전-->', dataAry)
dataAry = selectionSort(dataAry)
print('정렬 후-->', dataAry)
정렬 전--> [119, 163, 187, 133, 195, 152, 142, 168, 118, 177]
정렬 후--> [118, 119, 133, 142, 152, 163, 168, 177, 187, 195]

2) 검색

  • 검색은 정렬된 상태에서 빠르게 원하는 것을 찾을 수 있음.

검색의 개념

  • 어떤 집합에서 원하는 것을 찾는 것으로, 탐색이라고도 함
  • 검색에는 순차 검색, 이진 검색, 트리 검색 등이 있음
  • 검색에 실패하면 -1을 반환하는 것이 일반적임

검색 알고리즘의 종류

  • 순차 검색
    • 검색할 집합이 정렬되어 있지 않은 상태일 때
    • 처음부터 차례대로 찾아보는 것으로, 쉽지만 비효율적
    • 집합의 데이터가 정렬되어 있지 않다면 이 검색 외에 특별한 방법 없음
  • 이진 검색
    • 데이터가 정렬되어 있다면 이진 검색도 사용 가능
    • 순차 검색에 비해 월등히 효율적이라 데이터가 몇 천만개 이상이어도 빠르게 찾음
  • 트리 검색
    • 데이터 검색에는 상당히 효율적이지만 트리의 삽입, 삭제 등에는 부담

순차 검색

전역
import random
SIZE = 10
dataAry = [random.randint(1,99) for _ in range(10)]
findData = dataAry[random.randint(0, SIZE-1)]
함수
def seqSearch(ary, fData):
    pos = -1
    size = len(ary)
    for i in range(0, size, 1):
        if (ary[i] == fData):
            pos = i
            break
    return pos
        
메인
print('배열-->', dataAry)
position = seqSearch(dataAry, findData)
if position == -1:
    print(findData, '없어요 ㅠ')
else:
    print(findData, '가', position, ' 에 있음')
배열--> [7, 45, 32, 60, 31, 81, 82, 97, 74, 80]
31 가 4  에 있음

이진 검색

전역
import random
SIZE = 10
dataAry = [random.randint(1,99) for _ in range(SIZE)]
findData = dataAry[random.randint(0, SIZE-1)]
dataAry.sort()
함수
def binSearch(ary, fData):
    pos  = -1
    start = 0
    end = len(ary) - 1
    while (start <= end):
        mid = (start + end) // 2
        if fData == ary[mid]:
            return mid
        elif fData > ary[mid]:
            start = mid + 1
        else:
            end = mid - 1
    
    
    return pos
        
메인
print('배열-->', dataAry)
position = binSearch(dataAry, findData)
if position == -1:
    print(findData, '없어요 ㅠ')
else:
    print(findData, '가', position, ' 에 있음')
배열--> [9, 14, 18, 24, 30, 54, 56, 58, 60, 94]
24 가 3  에 있음

3) 재귀

재귀 알고리즘이란?

  • 양쪽에 거울이 있을 때 거울에 비친 자신이 무한 반복해서 비치는 것 또는 마트료시카 인형처럼 동일한 작동을 무한적으로 반복하는 알고리즘을 말함

재귀 호출의 개념

  • 재귀 호출(Recursion)은 자신을 다시 호출하는 것

재귀 호출의 작동

  • 상자를 반복해서 여는 과정을 재귀 호출 형태로 표현

1.무한 반복

전역

def openBox():
    print('박스를 엽니다~~~')
    openBox()

함수


메인

openBox() # 무한 루프 
  1. 횟수를 정해놓고 작동

전역

count = 10 # 10번만 작동하게 변수 작성

함수

def openBox():
    global count
    print('종이 상자 열기~~~')
    count -= 1
    if count == 0:
        print('** 반지 넣기 **')
        return
    openBox()
    print('종이 상자 닫기!')
    return


메인

openBox()
종이 상자 열기~~~
종이 상자 열기~~~
종이 상자 열기~~~
종이 상자 열기~~~
종이 상자 열기~~~
종이 상자 열기~~~
종이 상자 열기~~~
종이 상자 열기~~~
종이 상자 열기~~~
종이 상자 열기~~~
** 반지 넣기 **
종이 상자 닫기!
종이 상자 닫기!
종이 상자 닫기!
종이 상자 닫기!
종이 상자 닫기!
종이 상자 닫기!
종이 상자 닫기!
종이 상자 닫기!
종이 상자 닫기!

재귀 호출 작동방식의 이해

숫자 합계 내기(1부터 10까지 합계를 구하는 예)

전역

함수
def addNumber(num):
    if num <= 1:
        return 1
    return num + addNumber(num-1)

메인
addNumber(10)
55

팩토리얼 구하기(10부터 1까지 곱하는 예)

전역

함수
def factorial(num):
    if num <= 1:
        return 1
    return num * factorial(num-1)
메인
factorial(10)
3628800

재귀 호출의 연습

우주선 발사 카운트 다운

전역

함수
def countDown(n):
    if n == 0:
        print('start!')
    else:
        print(n)
        countDown(n-1)

메인
countDown(10)
10
9
8
7
6
5
4
3
2
1
start!

별 모양 출력하기

  • 입력한 숫자만큼 차례대로 별 모양을 출력하는 코드
전역

함수
def printStar(num):
    if num > 0:
        printStar(num-1)
        print('★' * num)
메인
printStar(3)
★
★★
★★★

구구단 출력하기

  • 2단부터 9단까지 구구단을 출력하는 코드
전역

함수
def ggd(num1, num2):
    print(f'{num1} * {num2} = {num1*num2}')
    if num2 < 9:
        ggd(num1, num2+1)
        
메인
for i in range(2, 10):
    ggd(i, 1)
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
2 * 7 = 14
2 * 8 = 16
2 * 9 = 18
3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
3 * 4 = 12
3 * 5 = 15
3 * 6 = 18
3 * 7 = 21
3 * 8 = 24
3 * 9 = 27
4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16
4 * 5 = 20
4 * 6 = 24
4 * 7 = 28
4 * 8 = 32
4 * 9 = 36
5 * 1 = 5
5 * 2 = 10
5 * 3 = 15
5 * 4 = 20
5 * 5 = 25
5 * 6 = 30
5 * 7 = 35
5 * 8 = 40
5 * 9 = 45
6 * 1 = 6
6 * 2 = 12
6 * 3 = 18
6 * 4 = 24
6 * 5 = 30
6 * 6 = 36
6 * 7 = 42
6 * 8 = 48
6 * 9 = 54
7 * 1 = 7
7 * 2 = 14
7 * 3 = 21
7 * 4 = 28
7 * 5 = 35
7 * 6 = 42
7 * 7 = 49
7 * 8 = 56
7 * 9 = 63
8 * 1 = 8
8 * 2 = 16
8 * 3 = 24
8 * 4 = 32
8 * 5 = 40
8 * 6 = 48
8 * 7 = 56
8 * 8 = 64
8 * 9 = 72
9 * 1 = 9
9 * 2 = 18
9 * 3 = 27
9 * 4 = 36
9 * 5 = 45
9 * 6 = 54
9 * 7 = 63
9 * 8 = 72
9 * 9 = 81

N제곱 계산하기

전역
tab = ''
함수
def pow(x, n):
    global tab
    tab += '  '
    if n == 0:
        return 1
    print(f'{tab}{x}*{x}^{n}-{1}')
    return x * pow(x, n-1)
메인
pow(3,3)
      3*3^3-1
        3*3^2-1
          3*3^1-1





27

배열의 합 계산하기

  • 랜덤하게 생성한 배열의 합계를 구하는 코드
전역
import random
ary = [random.randint(0, 225) for _ in range(10)]
함수
def arySum(ary, n):
    if n <= 0:
        return ary[0]
    return arySum(ary, n-1) + ary[n]

메인
print(ary)
print('합계 ->', arySum(ary, len(ary)-1))

[20, 185, 8, 166, 205, 68, 83, 123, 192, 220]
합계 -> 1270

2022

[web]jQuery 복습 3

2 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]jQuery 복습 2

11 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]jQuery 복습 1

16 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리4

6 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리3

6 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리2

6 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리1

7 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]CSS 기초 정리

9 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]HTML 기초 정리

2 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[Pandas]pandas 연습

3 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

맨 위로 이동 ↑

2021

[Python기초]module

1 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

맨 위로 이동 ↑