[Code tree 조별과제]

✅ Topics

  • Function
  • Recursive function

1️⃣ Function

Code tree 로 진행하는 조별 과제는 Java 언어로 진행할 계획이다. Python 도 가능하나, 한국에서는 아직 백엔드로는 Java 가 대세이므로, Java 언어를 더욱 공부하려고 한다.

 

역량 진단 결과, 프로그래밍 연습 커리큘럼부터 진행해도 된다는 판단이 되어 함수 파트부터 진행하도록 하려고 한다.

 

Java 에서는 함수를 Method 라고 한다. 원래는 Method 가 함수의 한 종류이지만, 여기서는 깊게 들어가서 구분하지 않고 같은 것으로 바라보도록 하겠다.

 

함수, 즉 메서드는 내가 값을 입력하면 연산 결과가 출력된다. 중학교 때 배웠던 함수와 같은 원리로 이루어진다. 하지만, 함수는 블랙박스와 같아서 호출할 때는 외부에서 필요한 값만 입력하면 된다. 그렇다면 함수가 가진 장점은 무엇일까? 함수는 정의만 해주면 원할 때 언제나 재사용이 가능하다는 점이다.

 

메서드는 메서드 선언과 메서드 본문으로 나눌 수 있다. 

🛜 Method Declaration (메서드 선언)

public static int add(int a, int b)
  • Method name, Return type,  Paramater (매개변수) 목록을 포함한다.
  • 이 메서드 선언 정보를 통해 다른 곳에서 호출할 수 있다.
int sum1 = add(5, 10); // 5 + 10 = 15
int sum2 = add(15, 20); // 15 + 20 = 35

 

  • 이 메서드를 호출해서 실행하려면 메서드 이름에 입력 값을 전달하면 된다.

Argument (인수) 와 Parameter (매개변수) 와 헷갈리는 경우가 많아 용어를 정리해보겠다.

❗Argument (인수)
함수 (Method) 에 넘기는 값을 인수라고 한다. 실무에서는 Argument, 인수, 인자 라는 말을 다 같이 사용한다.

❗Parameter (매개변수)
메서드를 정의할 때 선언한 변수를 매개변수, 또는 파라미터라고 한다. 메서드를 호출할 때 인수를 넘기면 그 인수가 매개변수에 대입된다. 실무에서는 매개변수, 파라미터 둘 다 사용한다.

 

🛜 반환 유무에 따른 함수

함수는 타입을 가지는데, 그 타입에 따라 값을 반환하는지 반환하지 않는지가 달라진다. 

public static int add(int a, int b)

위에서 언급한 더하는 함수는 "int" 라는 타입을 가지고 있다. 이 메서드 본문에는 반드시 "Return value" 이 존재해야 한다. 그리하여 그 메서드가 정의한 것을 계산하여 결과를 도출하는 것이다.

 

1부터 특정 수까지의 합

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // 여기에 코드를 작성해주세요.
        Scanner input = new Scanner(System.in);

        // 정수 N
        int N = input.nextInt();
        input.close();

        int sum = sumNum(N);
        System.out.println(sum);

    }

    private static int sumNum(int N)
    {
        int totalSum = 0;

        for(int i = 1; i <= N; i++)
        {
            totalSum += i;
        }

        return totalSum / 10;
    }
}

"int" 라는 타입을 가진 sumNum method 는 반드시 return value 를 가져야 한다. 그래서 return totalSum 을 통해 함수의 반환값이 존재하는 것이다.

 

public static void print()

"void" 라는 타입을 가진 이 메서드는 "return value" 가 필요없이 단순히 메서드 안에서 출력되는 결과만 나온다.

 

함수를 이용해 직사각형을 만들기

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // 여기에 코드를 작성해주세요.

        Scanner input = new Scanner(System.in);

        // n과 m 입력
        int n = input.nextInt();
        int m = input.nextInt();

        squarePrint(n, m);

    }
    
    // 직사각형의 행, 열의 크기 출력 함수
    private static void squarePrint(int n, int m)
    {
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                System.out.print("1");
            }
            System.out.println();
        }
    }
}

 

위의 함수는 "void" 이다. 이 함수는 단순히 출력만 하므로, Return value 가 필요 없는 것이다.

 

🛜 Call by value / Call by reference

프로그래밍을 공부한 학생이라면 이 단어를 수없이 들어봤을 것이다. 학년이 낮은 과목에서는 이 둘을 구분하나, 깊게 들어가자면 사실 같은 의미이다. 알고리즘을 공부하고 있으므로 가볍게만 설명하도록 하겠다.

Java의 메모리 구조는 다음과 같은 3가지 영역을 가진다. 클래스 정보를 보관하는 메서드 영역,  실제 프로그램이 실행되는 스택 영역,

객체 (인스턴스)가 생성되는 힙 영역이 존재한다.

 

이것을 좀 더 구체적이고 실제적으로 표현하면 이와 같다.

 

간단히 말하자면, int value = 10 이라는 변수를 선언한 후, int value = 20 이라는 코드를 다시 실행한다고 하면 value 값 자체가 20으로 바뀌는 것이 아닌, value=20 이라는 인스턴스를 value 변수가 가리키는 것으로 바뀐다는 것이다. 결국 값은 그대로 있는 것이고 참조값이 바뀌는 것이 이 문제의 핵심이다. 

 

Recursive Function (재귀함수)

재귀함수는 함수 안에서 자신의 함수를 다시 호출하는 함수를 말한다. 보통 재귀함수는 반복문과 많이 비교된다. 

함수는 사용될 때 stack memory를 사용하는데, 자기 자신을 계속해서 호출하게 된다면 메모리를 많이 사용할 수 밖에 없다.

그렇기 때문에 반복문에 비해 메모리 크기가 커서 효율성이 좋지 않다. 만일 메모리가 부족하다면 Stack OverFlow가 발생하여 프로그램이 비정상적으로 종료된다. 그렇다면 재귀함수를 사용하는 것이 있을텐데 왜 사용하는 것일까?

 

재귀함수를 사용하는 가장 중요한 이유는 "짧은 코드 길이와 가독성" 때문이다. 반복문은 코드 길이도 재귀함수에 비해 길어지고, 재귀함수에 비해 많은 변수를 선언하는 것과 달리 재귀함수는 그렇지 않기 때문이다.

 

따라서, 재귀함수를 사용하든 반복문을 사용하든 각 프로그램에서 지향하는 바에 따라 다르고, 프로그래머가 선택할 수 있는 영역이다.

 

 

 

'Algorithm' 카테고리의 다른 글

Baekjoon - 정렬  (1) 2024.10.01
Baekjoon - Brute-Force  (5) 2024.09.18
Baekjoon Time-complexity  (1) 2024.09.18
[코드트리 조별과제] 3 days - TIL  (0) 2024.08.15
[코드트리 조별과제] 2 Days - TIL  (1) 2024.08.04