반갑습니다.
폭염에 찌들어 가고 있는 중에..
책을 보다가 재귀함수에 대해서 언급한 내용이 있어서 여러분들은
어떻게 사용하고 계시는지 궁금해서 글을 써 봅니다.
과거 제가 사용한 예 입니다.
http://www.androidpub.com/1055866
제가 직접 사용 해보니 Recursive Fuction 은 제약사항이 많은데
저는 이런 이유들 때문에 사용하거나 피하거나 합니다.
단점들..
1. Fuction Call 할때 비용이 비싸다는것..
2. Stack Overflow 가 발생될 수 있다는것..
3. Escape 를 찾지 못할 경우 무한루프에 빠진다는것..
4. 중간에 끊어 졌을때 디버깅이 힘들다는 것..
5. 복잡한 비교를 통해서 경우에 따라 호출 할 경우 이해하기 힘들다는것..
6. 제일 중요한 이유중 하나로써.. 재귀함수로 안만들어도 대체 가능하다는것..
장점들..
1. 코드가 간결해 진다.
2. 논리적으로 반복되는 경우 재귀함수를 사용하면 편하다
3. Stack Overflow의 경우 functionCount 를 설정해서 원하는 depth 까지 정할 수 있으므로
두려워 할 필요가 음따..
4. 구차한 변수 선언 및 if ~ else 를 피할수 있어서 성능에 도움이 될 수 있다.
( if ~ else 문이 엄청나게 많을 경우 ..)
제가 요로코롬 사용중에 있었는데 책에서 "팩토리얼을 재귀함수로 사용하는 직원이 있으면 바로 해고하겠다"
라고 쓰여 있더군요.. 그 이유는 재귀함수는 그렇게 단순한 형태로 쓰이는게 아니다.. 라고 하네요..
보통 문법책에서 재귀함수를 팩토리얼로 예시 하는데 무서운 이야기 더군요..ㅎㅎ
트리형태의 어떤 구조(자료구조, XML, 기타:결국은 다 똑같나) 를 사용할때 항상 쓰게되던데요.
물론 그게 자주는 아닙니다.
실무경력 18년찬데, (20 번은 넘을라나) 많지 않습니다.
횟수는 기억안납니다.
그리고 극단적인 성능의 차이가 나는게 아닌한 로직의 표현이 분명하다면 쓰는게 낫다고 생각합니다.
(소스 유지보수측면)
디렉토리 검색할때 사용하는데요.
희한하게 정말 "2. Stack Overflow 가 발생될 수 있다는것.." 하는 경우가 있더라구요.
폴더 depth가 깊어봐야 얼마나 깊다고 스택오버플로어가 나오나 생각되는데
실제로 나오기는 하더군요. 아직도 이 문제는 해결을 못했답니다.
트리탐색이나 문자열 파싱 특히 XML 파싱때 외엔
사용해 본 적이 없습니다..
잘 쓰면 편할 수도 있고 안써도 별 불편이 없지만
재귀함수 아니면 안돼는 경우가 가끔은 있더군요.
미신은 미신일뿐.
예전에 goto문 쓰는걸 엄청난 죄악으로 여기던적이 있었죠.( 지금도 어느정도 그렇죠. )
리눅스 커널보면 goto문이 도배가 되어 있습니다.
예외 처리할때 그보다 간결한 방법이 없기때문이죠.
요는 제대로 알고, 적시 적소에 쓸수 있는 능력이 있는가 없는가가 문제입니다.
goto 문이나 재귀함수, 기타 금기시되어 있는 테크닉들이 일종에 무속신앙처럼 미개한것으로 치부되는 현실이 안타갑네요.
재귀함수가 그리 나쁜 건 아닌 듯 한데...
체스 인공지능에서 MinMax + Alpha Beta Pruning을 비 재귀함수로 변환하려 시도해 본 적이 있습니다.
논리적으로 모든 재귀함수는 비재귀함수로 변환가능하다는데.
저로서는 도저히 불가능하더군요.
역시 재귀함수가 아니면 안되는 경우가 있는 것 같습니다.
거기에 존재의의가 있는 듯.
바꿀 수 있다고 하지만. 바꾸기 힘든 경우가 많습니다.
어떠한 문제가 닥쳤을 때, 단순 분할정복법이나 DFS 만 하더라도 재귀를 비재귀로 바꾸면 코딩양이 엄청나게 늘어납니다. 나중에 그에 대해 최적화가 필요할 땐 재귀를 비재귀로 바꾸기 보다는 cutting 함수를 잘만드는게 좋겠죠. 진짜 정 방법이 없으면 비재귀로 하는거고...
완전 속도 크리티컬하지 않다면 재귀를 비재귀로 바꾸는 비용이 생각보다 크다라는겁니다. A 가 B 호출하고 B 가 A 호출하는 재귀구조도 있을 수 있는데, 변환하는 가이드 라인이 있긴 하지만... 글쎄요. 해보시면 알겠지만 cutting 잘해주는게 더 좋습니다.
성능면에서만 보자면 재귀보단 비재귀가 좋겠지만
코드 간결성이나 사람입장에서는 재귀가 더 와닿지 않나요?
재귀를 비재귀로 만드는대 드는 노력도 비용이라면 비용이랄수 있겠고ㅎ
팩토리얼은 루프 한번이면 되는걸 생각없이 재귀로 만들어서 그런말이 나온거 아닐까요..
재귀의 나쁜 예로는 피보나치 수 구하기 같은거..
fib(5) = fib(4)+fib(3)
fib(4) = fib(3)+fib(2)
fib(3) = fib(2)+fib(1)
...
함수 한번 호출 할때마다 재귀로 함수호출이 두번씩 일어나고,
fib(5) 안에서 fib(3)을 계산하는 경우 앞서 fib(4)를 계산할때 구했던 값[fib(3)과 fib(3)]을 활용하지 않고
다시 무식하게 계산하는.. 최악의 효율을 보여주는 재귀죠;;
이런 예에서는 재귀가 좋은게 못되지만
중복 계산을 하지 않는 경우나 분할정복같은 예에서는
이해하기 쉽고 간결한 재귀가 더 좋아보여요.
사실 저도 팩토리얼 이후에는 한 번도 사용해 본 적은 없네요;
C를 안해서 그런가;