[JSアルゴリズム]再帰(Recursion)


再帰関数を使用する理由

  • What is recursion?
  • 回帰は自己(関数)呼び出しのプロセスである.A process (a function in our case) that calls itself
  • なぜわかるのですか?
    どこにもいないから
  • JSON.parse/JSON.stringify
  • ブラウザエンジンでは、JSONタイプは通常再帰を使用します.
  • document.getElementByIdとDOM巡回アルゴリズム
  • DOMは樹形構造であり、重複構造が多い.場合によっては、div内にdivが繰り返す100層のオーバーラップ構造がある可能性がある.このすべてを通じて、あなたは探求する時にあなたの幽霊を書くことができます.
  • 対象巡回
  • それ以外にも複雑なデータ構造からの解決策として、再帰を含むことが多い.
  • 呼び出しスタック

  • 再帰関数が自己呼び出しを続けると、その後何が起こるのでしょうか.有効な再帰関数を誤って記述しないためには,それを理解しなければならない.
  • ほとんどのプログラミング言語は、関数が呼び出されるとバックグラウンドで管理されるデータ構造があり、javascriptではcall stack
  • 呼び出しスタックの上部に関数が呼び出される.コンパイラはスタックの上部を実行してクリアします.
  • ブラウザ開発者ツールのウィジェットにコードを貼り付け、関数呼び出し文にbreakPointを掛けてCTRL Enterで実行し、F 9を押してcallスタックの流れを確認する.
  •     function takeShower() {
            return "샤워하자"
        }
        
        function eatBreakfast() {
            let meal = cookFood()
            return `${meal}를 먹자`
        }
        
        function cookFood() {
            let items = ['김치찌개', '미역국', '된장찌개']
            return items[Math.floor(Math.random()*items.length)];
        }
        
        function wakeUp() {
            console.log(takeShower());
            console.log(eatBreakfast());
            console.log("이제 출근하자")
        }
        
        wakeUp();
  • 再帰関数を記述する場合、callスタックを使用して操作することが多い.
  • 再帰関数は呼び出しスタックに新しい関数(同じ関数)を押し込み続ける.
  • JSON.解析はJSONです.parseを呼び出し続けると、呼び出しスタックにJSONがあります.parseでJSON.parse、上はJSONです.parseはこうなったそしてある瞬間に停止する(条件を与えなければならない).
  • 再帰関数に必要な2つの部分

  • 再帰関数に必要な2つの部分
  • Base Case
  • Base Caseは帰宅停止の条件.
  • その他入力値
  • 同じ関数を呼び出しても、毎回異なるデータを入力しなければならない.(減少)
  • function countDown(num) {
        if(num <= 0) {   // 1. Base Case
            console.log("All done!");
            return;  
        }
        console.log(num);
        num--;  // 2. 매번 다른 값 입력
        countDown(num);
    }
    
    countDown(5);
    // 재귀를 이용한 sum 함수
    function sumRange(num) {
        if(num === 1) return 1; // Base Case
        return num + sumRange(num-1); // 다른 input
    }
    
    sumRange(3) // 6
    
    // return 3 + sumRange(2);
               // return 2 + sumRange(1);
                            // return 1;
    // 재귀를 이용한 팩토리얼 함수
    function factorial(num) {
        if(num===1) return 1; // Base Case
        return num * factorial(num-1); // 다른 input
    }
    
    factorial(4)

    鬼を間違えた。

  • 不適切な使用
  • ベースなしCase
  • 返却忘れまたは返却エラー
  • Stack overflow
  • スタック内の関数呼び出しが多すぎて最大呼スタックサイズを超えている
  • コールスタックから見ると、すべてが互いに依存し合い、待ち合っている.チェーンに接続されているように、最後に値を返し、加算または乗算し、前に戻し、元の関数呼び出し文に影響します.
  • 再帰的な2つの設計モード


    1.Helperメソッドのリスニング

  • 再帰とともに使用される設計モードにはhelperメソッド再帰がある.
  • 再帰関数に空の配列を定義して後で返す値を定義すると、再帰呼び出しのたびに初期化の問題があるため、再帰関数のみを定義できます.次に、その再帰関数を囲む別の関数を作成します.
  • helperメソッド再帰は、外部関数が再帰関数である内部関数を呼び出す形式である.
  • 例(アレイ内の全ての穴を収集する関数)
  •     function collectOddValues(arr){
            
            let result = [] // 데이터를 저장한 빈 배열, 이 빈 배열을 재귀함수 안에 정의하면 재귀호출시마다 초기화되는 문제가 있으므로, 재귀함수 밖에 정의한다.
        
            function helper(helperInput){
                if(helperInput.length === 0) {
                    return;
                }
                
                if(helperInput[0] % 2 !== 0){
                    result.push(helperInput[0])
                }
                
                helper(helperInput.slice(1))
            }
            
            helper(arr) // 헬퍼 메소드 재귀는 재귀형이 아닌 외부 함수가 재귀형인 내부 함수를 호출하는 형태이다.
        
            return result;
        }
        
        collectOddValues([1,2,3,4,5,6,7,8,9])

    2.ピュア回帰

        function collectOddValues(arr){
            let newArr = [];
            
            if(arr.length === 0) {
                return newArr;
            }
                
            if(arr[0] % 2 !== 0){
                newArr.push(arr[0]);
            }
                
            newArr = newArr.concat(collectOddValues(arr.slice(1)));
            return newArr;
        }
        
        collectOddValues([1,2,3,4,5]);
        // [1].concat(collectOddValues([2,3,4,5]))
        								// [].concat(collectOddValues([3,4,5]))
        																// [3].concat(collectOddValues([4,5]))
        																								// [].concat(collectOddValues([5]))
        																															// [5].concat(collectOddValues([]))
        																																				// []
        
        // [1].concat([3].concat[5])
        // [1,3,5]
  • 擬似純再帰関数では、関数が再帰的に呼び出されるたびに、戻り値を含む配列が空の配列に初期化される.しかし、ここの違いは、気にする必要がないことです.今度はそうするつもりだ.
  • ここでは、配列を一番後ろにまとめてから戻ります.
  • 純関数Tip使用
  • 배열では、配列を変更せずにsliceなどのメソッドまたは展開演算子およびconcatメソッドを使用して配列をコピーします.
  • 문자열変わらず、sliceやsubstry、substringなどの方法で文字列をコピーできます.
  • 객체を例に、対象とする.割り当てオペレータまたは展開オペレータを使用してオブジェクトをコピーできます.
  • これにより結果値が蓄積される.

  • HMMM...