재귀 함수란 자기 자신을 다시 호출하는 함수를 말한다.
하지만 이러한 개념을 알고 있어도 직접 구현할려고 하면 헷갈린다.
특히, 분기를 위한 반복문이 함수내에 들어간다면 더더욱 그렇다.
거리 계산 다이어그램을 예로 해서 살펴보자
위 다이어그램의 숫자들은 각 점끼리의 거리이다.
즉, 총 거리는 숫자들을 모두 더한 13이고,
D까지는 3 + 2 + 4 = 9가 된다.
재귀 함수로 코드화 해보자
private static int NAME_A = 0;
private static int NAME_B = 1;
private static int NAME_C = 2;
private static int NAME_D = 3;
private static int NAME_E = 4;
private static int NAME_F = 5;
private static int NAME_G = 6;
private static int NAME_H = 7;
private int getDistance(int[] points, int index, int searchindex, int distance) {
//거리 누적
distance += points[index];
Log.d("MyLog", "getDistance: " + distance);
//목적지까지 도착하면 멈춤
if(index == searchindex)
return distance;
//다음 점으로 재귀 호출
return getDistance(points, ++index, searchindex, distance);
}
//점의 거리 배열
int[] points = {0, 3, 2, 4, 3, 1};
//D까지의 거리 계산
int distance = getDistance(points, NAME_A, NAME_D, 0);
Log.d("MyLog", "Distance: " + distance);
결과 :
D/MyLog: getDistance: 0
D/MyLog: getDistance: 3
D/MyLog: getDistance: 5
D/MyLog: getDistance: 9
D/MyLog: Distance: 9
여기까지는 원래 반복문 하나로도 구현 가능하다
하지만 중간에 분기가 포함되면 재귀 함수의 면모가 드러난다
위 다이어그램은 C에서 두갈래로 갈라진다
코드로는 재귀 함수에 반복문을 추가해준다
//점 거리 클래스
private class Point {
public Point[] mNextPoint;
public int mDistance;
public Point(int distance, Point[] nextpoint) {
mDistance = distance;
mNextPoint = nextpoint;
}
}
private int getDistance(Point point, Point searchpoint, int distance) {
while (true) {
//거리 누적
distance += point.mDistance;
Log.d("MyLog", "getDistance: " + distance);
//목적지까지 도착하면 멈춤
if (point == searchpoint)
return distance;
//다음 점 찾기
Point[] nextpoints = point.mNextPoint;
if(nextpoints == null) {
//더이상 길이 없으면 종료
break;
}
else {
for (int i = 0; i < nextpoints.length; i++) {
if(i == 0) {
//첫번째 길은 계속 반복문을 돌림
point = nextpoints[i];
}
else {
//두번째 길부터는 재귀 호출
int result = getDistance(nextpoints[i], searchpoint, distance);
//목적지를 찾았을때에만 누적 거리 반환
//그렇지 않으면 이어서 반복문을 돌림
if(result >= 0)
return result;
}
}
}
}
return -1;
}
//점의 거리 배열
Point[] points = new Point[8];
points[NAME_H] = new Point(3, null);
points[NAME_G] = new Point(2, new Point[] {points[NAME_H]});
points[NAME_F] = new Point(1, null);
points[NAME_E] = new Point(3, new Point[] {points[NAME_F]});
points[NAME_D] = new Point(4, new Point[] {points[NAME_E]});
points[NAME_C] = new Point(2, new Point[] {points[NAME_D],points[NAME_G]});
points[NAME_B] = new Point(3, new Point[] {points[NAME_C]});
points[NAME_A] = new Point(0, new Point[] {points[NAME_B]});
//A에서 G까지의 거리 계산
int distance = getDistance(points[NAME_A], points[NAME_G], 0);
Log.d("MyLog", "Distance G: " + distance);
//A에서 E까지의 거리 계산
distance = getDistance(points[NAME_A], points[NAME_E], 0);
Log.d("MyLog", "Distance E: " + distance);
결과 :
D/MyLog: getDistance: 0
D/MyLog: getDistance: 3
D/MyLog: getDistance: 5
D/MyLog: getDistance: 7
D/MyLog: Distance G: 7
D/MyLog: getDistance: 0
D/MyLog: getDistance: 3
D/MyLog: getDistance: 5
D/MyLog: getDistance: 7
D/MyLog: getDistance: 10
D/MyLog: getDistance: 9
D/MyLog: getDistance: 12
D/MyLog: Distance E: 12
재귀 함수의 핵심은 반환값이다.
본류와 지류를 구분해 놓고
본류는 반복문이 계속 되게 놔두고 지류만 재귀 호출을 한다.
그리고 성공인지 실패인지 반환값을 받아 계속할지 끝낼지
결정하면 된다.
도움이 되셨다면~ 정성으로 빚은 저희 앱! 많은 이용 바래요:)
https://meorimal.com/index.html?tab=spaceship
https://meorimal.com/subway.html
'개발 > android' 카테고리의 다른 글
간단한 코딩으로 큰따음표("")로 묶인 CSV 파일 보기 (0) | 2016.11.14 |
---|---|
막대 그래프의 처음은 이렇게 (0) | 2016.10.24 |
TimePicker, DatePicker, NumberPicker의 폰트 바꾸기 (0) | 2016.07.18 |
카메라 위에 스킨을 넣어 찍어보자~ (1) | 2016.05.30 |
초간단 꺽은선 그래프 만들기 (4) | 2016.04.25 |