#keywords C++,재귀 êµê³¼ì„œì— ë³´ë©´ ëª¨ë“ ìž¬ê·€ íƒìƒ‰ì€ 루프로 구현 ê°€ëŠ¥í•˜ë‹¤ê³ ì 혀 있다. ì¼ë°˜ì 으로 ì´ë ‡ê²Œ 구현한다. 재귀가 반복문보다 메모리를 ë§Žì´ ì°¨ì§€í•˜ë©° ì†ë„ê°€ ëŠë¦¬ë‹¤ê³ 하지만 ì´ê±´ ì–¸ì–´ì— ë”°ë¼ ë‹¤ë¥´ë‹¤. ê·¸ë¦¬ê³ ì»´íŒŒì¼ëŸ¬ì— ë”°ë¼ ë‹¤ë¥´ë‹¤. ê·¸ë¦¬ê³ ë°ì´í„° ì…‹ì— ë”°ë¼ ë‹¤ë¥´ë‹¤. ì¼ë°˜ì 으로 루프로 ì§ì ‘ 구현하는건 ë“œë¼ë§ˆí‹±í•˜ê²Œ ì†ë„ê°€ 빨ë¼ì§€ì§€ëŠ” 않는다. 컴파ì¼ëŸ¬ê°€ 꼬리 재귀(tail recursion, returnì—ì„œ 추가 ì—°ì‚°ì„ í•„ìš”ë¡œ 하지 않는 형태) 최ì 화가 가능한 형태로 재귀 íƒìƒ‰ì„ 구현하는 ê²ƒì´ ë‚«ë‹¤. __컴파ì¼ëŸ¬ê°€ 꼬리 재귀를 최ì í™” í• ìˆ˜ 있으면 최ì í™” 하는 ê³¼ì •ì—ì„œ 꼬리 재귀를 반복문으로 변경한다__. ë”°ë¼ì„œ 기존 ìž¬ê·€ì˜ ë¬¸ì œì˜€ë˜ ë©”ëª¨ë¦¬ì™€ ì„±ëŠ¥ì— ëŒ€í•œ ë¬¸ì œê°€ ì œê±°ë˜ëŠ” 것ì´ë‹¤. (루프로 ì§ì ‘ 구현하면 재귀 깊ì´ê°€ 아주 커질 ë•Œ 스íƒì´ 깨지는 ê±´ 확실히 ë§‰ì„ ìˆ˜ 있다.) 재귀로 구현한 부분 ì§‘í•©ì˜ ëª¨ë“ ê²½ìš°ì˜ ìˆ˜ íƒìƒ‰ {{{#!gcode bool subsetsum(vector<int>& subset, int sum, int i) { if (i == subset.size()) { return true; } bool append = subsetsum(subset, sum + subset[i], i + 1); bool ignore = subsetsum(subset, sum, i + 1); return append || ignore; } }}} ---- 재귀로 구현한 부분 ì§‘í•©ì˜ ëª¨ë“ ê²½ìš°ì˜ ìˆ˜ íƒìƒ‰(꼬리 재귀) {{{#!gcode bool subsetsum_tail(vector<int>& subset, int sum, int i) { if (i == subset.size()) { return true; } return subsetsum(subset, sum + subset[i], i + 1) || subsetsum(subset, sum, i + 1); } }}} ---- 재귀 íƒìƒ‰ì„ 루프로 구현 {{{#!gcode void subsetsum_loop(vector<int>& subset, int sum, int i) { struct SnapShotStruct { int sum; int i; int stage; }; stack<SnapShotStruct> snapshotStack; SnapShotStruct currentSnapshot; currentSnapshot.sum = 0; currentSnapshot.i = 0; currentSnapshot.stage = 0; snapshotStack.push(currentSnapshot); while (!snapshotStack.empty()) { currentSnapshot = snapshotStack.top(); snapshotStack.pop(); switch (currentSnapshot.stage) { case 0: // subsetsum(subset, sum + subset[i], i + 1); { if (currentSnapshot.i == subset.size()) { continue; } currentSnapshot.stage = 1; snapshotStack.push(currentSnapshot); SnapShotStruct newSnapshot; newSnapshot.sum = currentSnapshot.sum + subset[currentSnapshot.i]; newSnapshot.i = currentSnapshot.i + 1; newSnapshot.stage = 0; snapshotStack.push(newSnapshot); } continue; case 1: // subsetsum(subset, sum, i + 1); { currentSnapshot.stage = 2; snapshotStack.push(currentSnapshot); SnapShotStruct newSnapshot; newSnapshot.sum = currentSnapshot.sum; newSnapshot.i = currentSnapshot.i + 1; newSnapshot.stage = 0; snapshotStack.push(newSnapshot); } continue; case 2: // return; continue; default: break; } } } }}} ---- ì†ë„ 비êµ(Release 모드, íƒìƒ‰ 30,000번) 재귀로 구현한 부분 ì§‘í•©ì˜ ëª¨ë“ ê²½ìš°ì˜ ìˆ˜ íƒìƒ‰ -- 0.0046s 재귀로 구현한 부분 ì§‘í•©ì˜ ëª¨ë“ ê²½ìš°ì˜ ìˆ˜ íƒìƒ‰(꼬리 재귀) -- 0.0022s 재귀를 반복문으로 구현 -- 0.0058s