봄이네집의 일고리즘 - 3) 파라미터를 숨기지 맙시다.

재귀함수 세 번째 이야기입니다.

재귀함수 얘기도 거의 끝나 가는데요, 오늘은 세 번째 시간입니다.

우리는 지난 시간까지 재귀함수의 여러 예제를 살펴보았고, 재귀함수의 몇 가지 설계 원칙에 대해서도 배워봤습니다. base case와 recursive case가 뭔지 알았고, 또 그것들이 꼭 포함되어 있어야 재귀함수가 제 기능을 할 수 있음을 배웠습니다.

base case가 실행되지 않는 재귀함수는 무한 루프에 빠진다는 것도 알게 됐습니다. 따라서 재귀함수를 설계할 때엔 base case를 구상한 후에 recursive case를 구현하는 것이 올바른 접근 방법임을 알게 됐습니다.

오늘은 또 다른 재귀함수 설계 원칙에 대해 알아볼까 합니다.

파라미터를 숨기지 맙시다!

파라미터가 뭐냐구요?

1
2
3
....
public static int hello(int count){
...

이 코드에서 메소드 hello는 정수형 count를 파라미터로 갖는 메소드입니다. 이해가 되시죠?

근데 이걸 어떻게 숨기냐고요? 아래 코드를 봐주세요.

1
2
3
4
5
6
7
8
9
10
...
int [] example = {1, 2, 3, 4, 5};

public static int find(int [] data, int target){
for (int i = 0; i < data.length; i++){
if (data[i] == target){
return i;
}
}
}

자, 어떠세요? 위 코드에서 find()는 파라미터로 받지 않은 값 두 개 를 사용하고 있습니다. 보이시나요?

for문을 봐 주세요. 우선 파라미터로 받지 않은 정수 i를 0으로 초기화해서 쓰고 있습니다. 반복문의 반복 횟수 또한 파라미터로 받지 않고, data.length로 알아내서 쓰고 있네요.

이렇게 파라미터를 숨겨 놓으면, 재귀함수를 구현할 수 없습니다.

정수 i와 data.length를 모두 파라미터로 입력받는 아래 코드를 봐 주세요.

1
2
3
4
5
6
7
8
9
10
11
12
13
public static int find(int [] data, int begin, int end, int target){
if (begin > end){
return -1;
}

else if (data[begin] == target){
return begin;
}

else{
return find(data, begin + 1, end, target)
}
}

이 코드에서 find()는 시작하는 위치를 표시해주는 정수 begin과 끝나는 지점을 표시할 정수 end를 통해 각각 i 와 data.length를 대신하고 있습니다.

이를 통해 재귀함수를 구현할 수 있게 되었습니다. base case는 begin > end로 잡아봤는데요, 시작점이 종점보다 크다면 원하는 데이터가 배열 안에 없다는 뜻이므로 -1을 리턴하고 메소드는 종료됩니다. 만약 배열 안의 begin번째 데이터가 원하는 값과 같다면, 그대로 begin을 반환하고 종료하면 됩니다.

아직 값을 찾지 못했다면, 자기 자신을 한 번 더 실행하면 됩니다. 단, 앞선 else if문을 통해 begin번째 데이터는 원하는 값이 아닌 것을 확인했으므로, 이번엔 begin + 1번째 데이터부터 들여다보면 되겠죠.

반복문을 수행할 때마다 i = 0으로 초기화시켜 쓰는 것이 아닌, 메소드의 파라미터를 통해 검색의 시작 위치를 지정해주니 이런 재귀적인 접근이 가능해지게 되었습니다.

정리

오늘은 명시적인 파라미터 (explicit parameters) 구현에 대해 알아보았습니다. 우리는 메소드를 만들면서 습관적으로 입력받지 않은 값을 끌어다 쓰는 코딩 습관을 가지고 있습니다. 특히 자바 프로그래머들 대다수는 파라미터를 통해 입력받은 값보다 그렇지 않은 값을 메소드 안에서 훨씬 더 많이 쓰고 있을 겁니다.

재귀함수를 구현하려면 그런 습관을 버려야함을 알게 되었습니다. 간단한 예제를 통해 명시적인 파라미터가 재귀함수의 구현에 어떤 도움을 주는지를 알아봤습니다.

또 메소드 내에서 파라미터로 전달받은 값만 사용하는 스타일의 프로그래밍이 유행하고 있습니다. 함수형 프로그래밍 이 그것인데요, 자바는 함수형 프로그래밍에 적합하지 않은 언어일 수도 있지만 그런 방법론을 적용해보는 것은 충분히 가능합니다.저도 관심있게 지켜보고 있는 방법론 중 하나인데요, 앞으로 심화학습해 보는 것도 좋을 것 같습니다.

오늘 사용한 예제, 그리고 오늘 배운 것을 연습할 수 있는 몇 가지 추가 예제가 제 깃헙 레포지토리에 올려져 있습니다.

오늘도 행복한 알고리즘 공부하세요! 감사합니다.