Skip to content

Latest commit

 

History

History
173 lines (121 loc) · 5.7 KB

File metadata and controls

173 lines (121 loc) · 5.7 KB

조건문과 반복문 (Control Flow)


개념 (Concept)

제어 흐름은 프로그램의 실행 순서를 정하는 방법이다. 조건문은 어떤 조건이 참일 때만 특정 코드를 실행하고, 반복문은 같은 작업을 여러 번 실행한다.

직관 (Intuition)

프로그램이 항상 위에서 아래로 한 번만 실행된다면 할 수 있는 일이 매우 제한된다. 조건문은 갈림길이고, 반복문은 되풀이 작업을 자동화하는 장치다.

  • 조건문: "비밀번호가 맞으면 로그인한다."
  • 반복문: "목록에 있는 모든 점수를 더한다."
  • 조기 종료: "원하는 값을 찾으면 더 찾지 않는다."
flowchart TD
    START["시작"] --> CHECK{"조건?"}
    CHECK -- 참 --> THEN["then 분기"]
    CHECK -- 거짓 --> ELSE["else 분기"]
    THEN --> LOOP{"반복 조건?"}
    ELSE --> LOOP
    LOOP -- 참 --> BODY["본문 실행 + 상태 갱신"]
    BODY --> LOOP
    LOOP -- 거짓 --> END["종료"]
Loading

이론 (Theory)

조건문은 불리언 표현식을 기준으로 분기한다.

if 조건:
    조건이 참일 때 실행
else:
    조건이 거짓일 때 실행

반복문은 보통 두 종류로 나뉜다.

종류 쓰임
for 반복문 정해진 범위나 컬렉션을 순회
while 반복문 조건이 참인 동안 계속 반복

반복문에는 종료 조건이 있어야 한다. 종료 조건이 없거나 갱신이 잘못되면 무한 루프가 된다.

불변식과 종료 조건

반복문을 깊게 이해하려면 두 질문을 한다.

  • 반복 불변식(loop invariant): 매 반복 시작 시 항상 참이어야 하는 사실은 무엇인가.
  • 종료 측도(variant): 반복이 진행될수록 줄어들어 결국 종료를 보장하는 값은 무엇인가.

예를 들어 최댓값 찾기에서 best는 "지금까지 본 값 중 최댓값"이라는 불변식을 갖는다. 인덱스 i는 매번 증가하고 배열 길이에 도달하면 종료한다.

구현 (Implementation)

조건문 예시:

score = 82

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
else:
    grade = "C or below"

print(grade)

반복문 예시:

scores = [90, 85, 100]
total = 0

for score in scores:
    total += score

average = total / len(scores)
print(average)

while은 반복 횟수가 미리 정해지지 않았을 때 유용하다.

n = 16
steps = 0

while n > 1:
    n //= 2
    steps += 1

print(steps)

워크드 예제:

values = [3, 1, 9, 2]
best = values[0]

for i in range(1, len(values)):
    if values[i] > best:
        best = values[i]

print(best)  # 9

반복 시작 시점마다 bestvalues[0:i]의 최댓값이다. i=1이면 [3]의 최댓값 3, i=3이면 [3,1,9]의 최댓값 9다. 이 불변식이 끝까지 유지되므로 반복 종료 뒤 best는 전체 배열의 최댓값이다.

복잡도 (Complexity)

구조 시간 공간
단일 조건문 O(1) O(1)
길이 n 목록 한 번 순회 O(n) O(1)
이중 반복문으로 n x n 순회 O(n^2) O(1)

반복문 개수만 세는 것보다 각 반복문이 몇 번 실행되는지를 계산하는 것이 중요하다.

예를 들어 while n > 1: n //= 2는 반복마다 n이 절반으로 줄어 O(log n)이다. 반면 while n > 1: n -= 1O(n)이다. 코드 모양보다 상태가 어떻게 변하는지가 복잡도를 결정한다.

응용 (Applications)

  • 입력값 검증
  • 목록 검색과 필터링
  • 누적합, 최댓값, 최솟값 계산
  • 시뮬레이션과 게임 루프
  • 알고리즘의 기본 골격 구성

흔한 오해 (Common Misunderstandings)

  • if가 여러 개 있는 것과 if / elif / else는 다르다. 전자는 조건을 각각 검사하고, 후자는 한 분기만 선택한다.
  • 반복문 안에서 제어 변수를 갱신하지 않으면 무한 루프가 될 수 있다.
  • break는 반복문 전체를 끝내고, continue는 현재 반복만 건너뛴다.
  • 중첩 반복문이 항상 O(n^2)은 아니다. 각 루프의 반복 횟수를 따로 봐야 한다.

TMI

  • 구조적 프로그래밍이 널리 퍼지기 전에는 goto로 실행 위치를 직접 옮기는 코드가 흔했다. Dijkstra의 "Go To Statement Considered Harmful"은 조건문, 반복문, 함수 중심으로 코드를 구조화하는 흐름에 큰 영향을 주었다.
  • Python의 for는 C/Java의 전통적인 카운터 반복문보다 "반복 가능한 값들을 하나씩 꺼낸다"는 의미에 더 가깝다.
  • Python에는 for ... else 문법이 있다. 반복문이 break 없이 끝났을 때 else가 실행되는데, 처음 보면 조건문의 else처럼 보여 헷갈리기 쉽다.
  • C와 Java에는 do ... while처럼 본문을 최소 한 번 실행하는 반복문이 있지만, Python에는 같은 모양의 전용 문법이 없다.

연습 / 확인 문제 (Exercises)

  • 1부터 100까지의 정수 중 짝수만 출력하라.
  • 주어진 점수 목록에서 최댓값과 평균을 구하라.
  • 숫자 목록에서 처음으로 음수가 나오는 위치를 찾고, 없으면 -1을 출력하라.

이어서 읽기 (Reading Path)

참조 (References)