//必要なスタックの基礎として js 配列を使用します
var stack = []
stack.get = function(){
return stack[stack.length - 1];
}
var list = []
//対象となる要素をリストに追加します。 testElem(el ){
if (el.className.split(' ').indexOf(name) > -1) {
list.push(el)>}
}
// ルート要素を確認します
testElem(elem);
// スタックを初期化します
stack.push({
pointer: elem,
num: 0
});
varparent, num, el;
while (true) {
parent = stack.get();
el =parent.pointer.children[parent.num]; el) { // ツリーのより深い層に入ります
testElem(el)
stack.push({
pointer: el,
num: 0
}); }
else {//上の層に戻ります
if (stack.pop().pointer === elem) {
break;
}
else {
スタック。 get() .num = 1;
}
}
}
リストを返します。
要約すると。すべてのループは再帰を使用して実装できます。すべての再帰はループを使用して実装できます。どの方法が使用されるかは、特定の問題やユーザーの好みに対して、どちらのアイデアがより便利で直観的であるかによって決まります。
効率 パフォーマンスの点では、再帰はループよりも利点がありません。複数の関数呼び出しのオーバーヘッドに加えて、場合によっては再帰により不必要な計算が繰り返される可能性があります。たとえば、フィボナッチ数列を計算する再帰プログラムを考えてみましょう。 n 番目の項目 A(n) を求める場合は、n-2 番目の項目から順に各項目を繰り返し計算します。項目数が少ないほど繰り返し回数が多くなります。 i 番目の項目が計算される回数を B(i) とすると、
B(i)=1、i=n, n-1
B となります。 (i)=B(i 1) B(i 2); i
このようにして、B(i) は興味深い逆フィボナッチ数列を形成します。 A(n)を求める場合:
B(i)=A(n 1-i)
見方を変えると、A(i)を求めるときはC(i)とします。必要な加算数は次のとおりです:
C(i)=0; i=0, 1
C(i)=1 C(i-1) C(i-1) ; i>1
D(i)=C(i) 1 とすると、
D(i)=1; i=0, 1
D(i) )=D(i-1) D(i-1)
したがって、D(i) は別のフィボナッチ数列を形成します。そして、次のように結論付けることができます:
C(n)=A(n 1)-1
そして、A(n) は、n が小さくなると、等比級数で増加します。大きくなるとかなりびっくりします。ループを使用する対応するプログラムは
B(n)=1; n は任意の値です
C(n)=0; n=0, 1
C(n )=n-1; n>1
したがって、n が大きい場合、上記のループを使用したプログラムは再帰を使用したプログラムよりもはるかに高速になります。
前のセクションのループと同様、再帰におけるこの欠陥も補うことができます。計算された項を覚えておくだけでよく、より上位の項を見つけるときは、前の項を直接読み取ることができます。この手法は再帰で一般的であり、記憶と呼ばれます。
以下は、ストレージ テクノロジーを使用してフィボナッチ数列を見つけるための再帰的アルゴリズムです。
//記憶付き再帰
関数fibonacci4(n ){
varmemory = []; //各計算項目の保存に使用
function calc(n){
var result, p,
if (n メモリ [n] = n;
return n;
else {
p = メモリ [n - 1] : calc(n - 1);
q = メモリ[n - 2] : 計算(n - 2);
メモリ[n] = 結果;結果;
}
}
戻り値
}