Learn and Understand Recursion in JavaScript - Lee-hyuna/33-js-concepts-kr GitHub Wiki
Learn and Understand Recursion in JavaScript
๋ฒ์ญ : https://codeburst.io/learn-and-understand-recursion-in-javascript-b588218e87ea
What is Recursion?
์ฌ๊ท๋ ๊ฐ๋จํ ํจ์๊ฐ ์์ ์ ํธ์ถํ ๋๋ฅผ ๋งํฉ๋๋ค.
๋ฐ๋ก ๋ฐ์ด ๋ค์ด ์๋ง๋ ๊ฐ์ฅ ์ ๋ช ํ ์ฌ๊ท ์์ ๋ฅผ ์ดํด ๋ณด๊ฒ ์ต๋๋ค. ์ด ์๋ ์ ๊ณต๋ ์ ์์ ๊ณ์น์ ๋ฐํํฉ๋๋ค.
function factorial(x) {
if (x < 0) return;
if (x === 0) return 1;
return x * factorial(x - 1);
}factorial(3);
**// 6**
** ์ฐ์ ๊ด์ฐฎ๋ค๋ฉด ๊ด์ฐฎ์ต๋๋ค. **. ์ค์ํ ๋ถ๋ถ์ 4 ๋ฒ ์ค์์ ์ผ์ด๋๊ณ ์์ต๋๋ค : return x * factorial (x โ 1);.
๋ณด์๋ค์ํผ, ํจ์๋ ์ค์ ๋ก ์์ ์ ๋ค์ ํธ์ถํ์ง๋ง (factorial (x-1)
), ์ฒ์ ํธ์ถ ํ์ ๋๋ณด๋ค 1์ด ์์ ๋งค๊ฐ ๋ณ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด๊ฒ์ ์ฌ๊ท ํจ์์
๋๋ค.
์ด ์ฝ๋ ์์ ๋ฅผ ๋ ์์ธํ ์ค๋ช ํ๊ธฐ ์ ์ ๊ณ์น์ด ๋ฌด์์ธ์ง ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
์ซ์์ ๊ณ์น์ ์ป์ผ๋ ค๋ฉด ์ซ์ 1์ ๋๋ฌ ํ ๋๊น์ง ๊ทธ ์ซ์์ 1์ ๋บ ๊ฐ์ ๊ณฑํ์ญ์์ค.
์์ 1: 4 ์ ํฉํ ๋ฆฌ์ผ์ 4 * 3 * 2 * 1, or 24.
์์ 2: 2 ์ ํฉํ ๋ฆฌ์ผ์ 2 * 1, or 2.
์ด์ ์ฐ๋ฆฌ ๊ณ ๋ฑํ๊ต ์ํ ์์ ์ด ๋๋ฌ์ผ๋, ์ข์ ๊ฒ๋ค๋ก ๋์๊ฐ ์ ์์ต๋๋ค!
The three key features of recursion
๋ชจ๋ ์ฌ๊ท ํจ์์๋ 3๊ฐ์ง ํน์ง์ด ์์ต๋๋ค.
A Termination Condition
if (๋ญ๊ฐ ๋์ ์ผ์ด ์๊ฒผ๋ค) {STOP};
์ข
๋ฃ ์กฐ๊ฑด์ ์ฐ๋ฆฌ์ ์ฌ๊ท ์คํจ ์์ ์
๋๋ค. ๋น์ ๋ธ๋ ์ดํฌ์ฒ๋ผ ์๊ฐํ์ญ์์ค. ์
๋ ฅ์ด ์๋ชป๋๋ฉด ์ฌ๊ท๊ฐ ์คํ๋์ง ์๋๋ก ํฉ๋๋ค. ํฉํ ๋ฆฌ์ผ ์์ ์์ if (x <0) return;
์ ์ข
๋ฃ ์กฐ๊ฑด์
๋๋ค. ์์๋ฅผ ๊ณ์น ํ ์ ์์ผ๋ฏ๋ก ์์๊ฐ ์
๋ ฅ ๋ ๊ฒฝ์ฐ ์ฌ๊ท๋ฅผ ์คํํ๊ณ ์ถ์ง ์์ต๋๋ค.
A Base Case
๊ฐ๋จํ ๋งํด : if (์ด๋ฌํ ์ผ) {์! ๋๋ฌ๋ค.};
๊ธฐ๋ณธ ์ฌ๋ก๋ ์ฌ๊ท๋ฅผ ์ค์งํ๋ค๋ ์ ์์ ์ข
๋ฃ ์กฐ๊ฑด๊ณผ ์ ์ฌํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ข
๋ฃ ์กฐ๊ฑด์ ๋์ ๋ฐ์ดํฐ์ ๋ํ ํฌ๊ด์ ์ธ ๊ฒ์์ ๊ธฐ์ตํ์ญ์์ค. ๊ธฐ๋ณธ ์ฌ๋ก๋ ์ฌ๊ท ํจ์์ ๋ชฉํ์
๋๋ค. ๊ธฐ๋ณธ ์ฌ๋ก๋ ์ผ๋ฐ์ ์ผ๋ก if
๋ฌธ ์์ ์์ต๋๋ค. ๊ณ์น ์์์ if (x === 0) return 1;
์ด ๊ธฐ๋ณธ ์ฌ๋ก์
๋๋ค. x ๋ฅผ 0์ผ๋ก ๋ฎ์ถ๋ฉด ๊ณ์น์ ๊ฒฐ์ ํ๋ ๋ฐ ์ฑ๊ณตํ์ต๋๋ค!
The Recursion
๊ฐ๋จํ ๋งํด์ : ์ฐ๋ฆฌ์ ํจ์ ์์ฒด๋ฅผ ํธ์ถํฉ๋๋ค. ๊ณ์น ์์์ return x * factorial (x โ 1);
์ ์ค์ ๋ก ์ฌ๊ท๊ฐ ๋ฐ์ํ๋ ๊ณณ์
๋๋ค. ์ฐ๋ฆฌ๋ ์ซ์ x
์ ๊ฐ์ factorial (x-1)
์ด ํ๊ฐํ๋ ๋ชจ๋ ๊ฐ์ ๊ณฑํ ๊ฐ์ ๋ฐํํฉ๋๋ค.
All Three Together
์ด์ ์ฐ๋ฆฌ๋ ๊ณ์น ์์ ๊ฐ ์ด๋ป๊ฒ ์๋ํ๋์ง ์ ํ ์์ง ๋ชปํ์ง๋ง ์ด์์ ์ผ๋ก๋ ์๋ฏธ๋ฅผ ๊ฐ๊ฒ ๋์์ต๋๋ค.
function factorial(x) {
**// TERMINATION**
if (x < 0) return; **// BASE**
if (x === 0) return 1; **// RECURSION**
return x * factorial(x - 1);
}factorial(3);
// 6
Factorial Function Flow
ํฉํ ๋ฆฌ์ผ ํจ์๋ฅผ ํธ์ถ ํ ๋ ์ด๋ค ์ผ์ด ๋ฐ์ํ๋์ง ์ ํํ๊ฒ ์ดํด ๋ณด๊ฒ ์ต๋๋ค.
- ๋จผ์ 3์ ๊ฐ์ ์ ๋ฌํ๋ ํจ์๋ฅผ ํธ์ถํฉ๋๋ค.
factorial(3);
- ์ด๋ก ์ธํด ๊ธฐ๋ฅ์ด ์คํ๋ฉ๋๋ค. if ๋ฌธ์ด ์คํจํ๊ณ ์ฌ๊ท ๋ผ์ธ์ด ์คํ๋ฉ๋๋ค.
factorial (3-1)
์ ๊ฐ๊ณผ 3์ ๊ณฑํ ์ ์๋ฅผ ๋ฐํํฉ๋๋ค.
return **3** * factorial(**2**);
factorial (2)
๊ฐ ์คํ๋๋ฉด if ๋ฌธ๋ค์ด ์คํจํ๊ณ ์ฌ๊ท๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ.factorial (2-1)
์ ๊ฐ์ 2์ ๊ณฑํ ๊ฐ์ ๋ฐํํฉ๋๋ค.
return **2** * factorial(**1**);
factorial (1)
์ด ์คํ๋๋ฉด if ๋ฌธ๋ค์ด ์คํจํ๊ณ ์ฌ๊ท๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ.factorial (1-1)
์ ๊ฐ 1์ ๊ณฑํ ๊ฐ์ ๋ฐํํฉ๋๋ค.
return **1** * factorial(**0**);
- factorial (0)์ด ์คํ๋๋ฉด ๋ค๋ฅธ ์ผ์ด ๋ฐ์ํฉ๋๋ค. 0์ด ๊ธฐ๋ณธ ์ฌ๋ก์ด๋ฏ๋ก if ๋ฌธ์ด ์ ๋ฌ๋๊ณ ํจ์๊ฐ 1์ ๋ฐํํฉ๋๋ค.
if (x === 0) return **1**;
์ด์ ํจ์๊ฐ ๋ง์นจ๋ด ๋ฐํ๋์์ผ๋ฏ๋ก ๋ชจ๋ ๊ฒ์ด 'ํ๋ฆฝ๋๋ค'. ์ฌ๊ท๋ ๋จ์ํ ์ค์ฒฉ ๋ ํจ์ ํธ์ถ ๊ทธ๋ฃน์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ค์ฒฉ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด most inner ์ค์ฒฉ ํจ์๊ฐ ๋จผ์ ๋ฐํ๋ฉ๋๋ค.
์ด๊ฒ์ ์ดํดํด์ผ ํ ์ค์ํ ๋ถ๋ถ์ ๋๋ค. ์ฒ์์ ์ดํดํ์ง ๋ชปํ๋ฉด์ด ๋ด์ฉ์ ๋ช ๋ฒ ์ฝ์ด๋ณด์ญ์์ค.
factorial(0)
returns 1
factorial(1)
returns 1 * factorial(0)
, or just 1*1
factorial(2)
returns 2 * factorial(1)
, or just 2*1*1
factorial(3)
returns 3 * factorial(2)
, or just 3*2*1*1
return 1 * 1 * 2 * 3
**// 6**
๋ฐ๋ผ ์๋์? ๋ค์์ ๋ค๋ฅด๊ฒ ๊ตฌ์ฑ๋ ๋์ผํ ์ค๋ช ์ ๋๋ค.
factorial(3) returns 3 * factorial(2)
factorial(2) returns 2 * factorial(1)
factorial(1) returns 1 * factorial(0)
factorial(0) returns 1// Now that we've hit our base case, our function will return in order from inner to outer:factorial(0) returns 1 => 1
factorial(1) returns 1 * factorial(0) => 1 * 1
factorial(2) returns 2 * factorial(1) => 2 * 1 * 1
factorial(3) returns 3 * factorial(2) => 3 * 2 * 1 * 1// 3 * 2 * 1 * 1 = **6**
์์ง๋ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ดํดํ์ง ์์๋ ๊ด์ฐฎ์ต๋๋ค. ํผ๋์ ํด์ํ๊ธฐ ์ํด ๋ค๋ฅธ ์์ ๋ก ๋์ด ๊ฐ์๋ค.
Lets look at a second example
์ด ๋ ๋ฒ์งธ ์์์๋ ์์ ํ ๋ค๋ฅธ ๊ธธ์ ๊ฐ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ ์ธํฐ๋ท์์ ์ธ๊ธฐ์๋ ๋ ๋ค๋ฅธ ์์ด๋ฉฐ ๋ฌธ์์ด์ ๋ค์ง๋ ๊ฒ๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค.
์ด ๋ฐฉ๋ฒ์ JavaScript์์ ๋ฌธ์์ด์ ๋ค์ง๋ ๊ฐ์ฅ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ ์๋๋๋ค. ํจ์ฌ ๋น ๋ฅธ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์ฌ๊ท์ ์ผ๋ฐ์ ์ธ ์ธํฐ๋ท ์ ์ผ ๋ฟ์ด๋ฏ๋ก ์ด๋ฅผ ๋ค๋ฃจ๊ณ ์ถ์์ต๋๋ค.
๋ค์ ์ฝ๋๋ฅผ ๋ณด์ญ์์
function revStr(str){
if (str === '') return '';
return revStr(str.substr(1)) + str[0];
}
revStr('cat');
// **tac**
Instantly you can (ideally) notice a few things:
str === ""
๊ฐ ์ฐ๋ฆฌ์ ๊ธฐ๋ณธ ์ฌ๋ก์ ๋๋ค. ์ฐ๋ฆฌ์ ๋์ ๋ฌธ์๊ฐ ์์ผ๋ฉด ์ฑ๊ณตํ์ต๋๋ค.return revStr (str.substr (1)) + str [0];
์ ์ฌ๊ท ๋ง์ ์ด ์ผ์ด๋๋ ๊ณณ์ ๋๋ค.- ์ฌ๊ธฐ์ ์ข ๋ฃ ์ฌ๋ก๊ฐ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ๊ธฐ๋ณธ ์ฌ๋ก๊ฐ ์ข ๋ฃ ์ฌ๋ก์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ์์ ๋ฌธ์๊ฐ ํฌํจ ๋ ๋ฌธ์์ด์ ์ป์ ์ ์์ต๋๋ค. ํจ์์๋ง ๋ฌธ์์ด ๋ง ์ ๋ ฅํ๋ฉด ๊ด์ฐฎ์ ๊ฒ์ ๋๋ค.
Letโs break it down line by line
์ด ์์์๋ ๋ฌธ์์ด cat
์ ๋ฐ์ ์ํต๋๋ค. ์ฐ๋ฆฌ๋ ํจ์๋ฅผ ํธ์ถํ๊ณ ๋ฌธ์์ด cat์ ์ ๋ฌํ๋ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค.
revStr('cat');
์ฌ๊ท ์ฌ๋ก๊ฐ ์คํ๋ฉ๋๋ค.
JavaScript์์ substr ()
๋ฉ์๋๋ ์ง์ ๋ ์์น์์ ์์ํ๋ ๋ฌธ์์ด์ ๋ฆฌํดํฉ๋๋ค. สปcat'.substr (1) ===โatโ
str [0]
์ ๋ฌธ์์ด์์ ํด๋น ์ธ๋ฑ์ค์ ๋ฌธ์๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋ฐ๋ผ์ cat [0] === 'c'
return revStr(str.substr(1)) + str[0];// SAME AS
return revStr('at') + 'c'
์ฌ๊ท ์ฌ๋ก๊ฐ ๋ค์ ์คํ๋ฉ๋๋ค.
return revStr(str.substr(1)) + str[0];// SAME AS
return revStr('t') + 'a'
์ฐ๋ฆฌ์ ์ฌ๊ท ์ฌ๋ก๋ ๋ง์ง๋ง ํ ๋ฒ ์คํ๋ฉ๋๋ค.
return revStr(str.substr(1)) + str[0];// SAME AS
return revStr('') + 't'
์ด๋ฒ์๋ ๊ธฐ๋ณธ ์ฌ๋ก๊ฐ ์คํ๋๊ณ ํจ์๋ ๋น ๋ฌธ์์ด์ ๋ฐํํฉ๋๋ค.
if (str === '') return '';
์ด์ ํจ์๊ฐ ๋ฐํ๋์์ผ๋ฏ๋ก ๋ชจ๋ ๊ฒ์ด 'ํ๋ฆฌ๊ณ '์์๋๋ก ๋์์ต๋๋ค.
return โโ + โtโ + โaโ + โcโ
// **tac**
Break it down even more
revStr('cat') returns
revStr('at') + 'c'revStr('at') returns
revStr('t') + 'a'revStr('t') returns
revStr('') + 't'revStr('') returns ''
revStr('') returns '' => ''
revStr('t') returns revStr('') + 't' => '' + 't'
revStr('at') returns revStr('t') + 'a' => '' + 't' + 'a'
revStr('cat') returns revStr('at') + 'c' => '' + 't' + 'a' + 'c'
**// tac**