2016-11-26 18 views
0

私は以下のコードを持っています。それは入力を受け入れ、ハノイの問題を解決するために行単位で印刷します。 3
ステップ1:再帰関数の呼び出しをカウントする方法(1ずつインクリメント)| C++


は、ディスクの数を入力します:1、私がやりたいことのすべては、以下の例のような手順の最後まで1から、その上の各ラインSTEP1、STEP2で印刷することです - > 2元のペグから1つのディスクを余分なペグに移動
ステップ2:1→3元のペグから1つのディスクを移動先のペグに移動
ステップ3:2→3 1つのディスクをあなたが必要なときに目的地への余分なペグは、再帰で

#include <iostream> 
int count=1; 
    void ToH(int dskToMv, int cLocation, string orpeg, int tmpLocation, string expeg, int fLocation, string depeg) 
    { 
     if(dskToMv != 0) 
     { 
count++; 
      ToH(dskToMv-1, cLocation, orpeg, fLocation, depeg, tmpLocation, expeg); 
      cout<<"Step "<<count<<": Move one disk from the "<< orpeg << " to the " << depeg 
       << " " << cLocation << " -> " << fLocation << endl; 
      ToH(dskToMv-1, tmpLocation, expeg, cLocation, orpeg, fLocation, depeg); 
     } 
    } 

    int main() 
    { 
     int c; 
     cout << "Enter the number of disks: "; 
     cin >> c; 
     ToH(c, 1, "original peg ", 2, "extra peg", 3, "destination peg"); 
    } 
+0

がToHが ''に別のint型step'パラメータを追加できます() 'そのすべての呼び出しで増加。 –

+0

ループが必要ですか? –

+0

ループが再帰より優れているかもしれませんが、1つの必要はありません。 –

答えて

0

ペグいくつかの方法があります:

  1. プリミティブグローバル変数 - これらは単一の状態だけを保持することができます。再帰分岐などでは、あるブランチが別のブランチが使用している値を上書きするため、再帰ブランチなどが機能しない可能性があります。単にカウントなどのものを格納するためには、これらはうまくいく傾向があります。

  2. 関数へのパラメータの受け渡し - 関数へのパラメータは、スタックに格納されます。関数が呼び出されると、それらはプッシュされます。したがって、各再帰では、繰り返し呼び出しごとにパラメータ値の「スタック」が作成されます。異なるブランチは他の値を破壊しないので(ファンクションコールの最後にポップが発生し、コールがプッシュした値だけがポップされるため)、これは再帰でうまくいきます。

  3. 複雑なグローバルデータ構造を使用します。これらは本質的に関数呼び出しの外にパラメータを格納し、より複雑な処理(例えばスタックの代わりにキューを使用する)を可能にするが、より多くの作業を必要とする。関数の外部にあるため、必要に応じて他のブランチが参照できます。

あなたがする必要があるのは、グローバルなintを宣言し、それを関数呼び出しでインクリメントすることだけです。関数が呼び出されるたびに、値がインクリメントされ、関数呼び出しの数がカウントされます。インクリメントされているだけなので、ブランチングに問題はありません(すべてのブランチは同じことをするため、区別がつかないため)。また

int count = 0; 
void ToH(int dskToMv, int cLocation, string orpeg, int tmpLocation, string expeg, int fLocation, string depeg) 
{ 
    count++; 
    if(dskToMv != 0) 
    { 
     ToH(dskToMv-1, cLocation, orpeg, fLocation, depeg, tmpLocation, expeg); 
     cout<<" Move one disk from the "<< orpeg << " to the " << depeg 
      << " " << cLocation << " -> " << fLocation << " - " << count << endl; 
     ToH(dskToMv-1, tmpLocation, expeg, cLocation, orpeg, fLocation, depeg); 
    } 
} 

あなたはバックトラックので、実際には「レベル」カウントを可能にする場合は、あなただけのパラメータを使用することができます。

void ToH(int dskToMv, int cLocation, string orpeg, int tmpLocation, string expeg, int fLocation, string depeg, int count = 0) 
{ 
    if(dskToMv != 0) 
    { 
     ToH(dskToMv-1, cLocation, orpeg, fLocation, depeg, tmpLocation, expeg, count + 1); 
     cout<<" Move one disk from the "<< orpeg << " to the " << depeg 
      << " " << cLocation << " -> " << fLocation << " - " << count << endl; 
     ToH(dskToMv-1, tmpLocation, expeg, cLocation, orpeg, fLocation, depeg, count + 1); 
    } 
} 

すべての方法が同じわけではありません。再帰が大規模な分岐データ構造上の一種の「検索」であると考えることを学ぶとき、これらのことを考えるのは簡単です。反復と同等の単純な再帰のみを使用する場合、これらの異なるメソッド間の区別はあまりありません。

+0

それは1だけ増分していません。 –

+0

if文の前に数えを出力すると動作します。私がif文の中で印刷すると、数字のカウントが間違っています –

+0

@Eternalそれは間違っています。 ToHへの呼び出しが2回あるため、すべての再帰で発生するバイナリ分岐があります。したがって、事前注文型のトラバーサルで印刷しています。つまり、最初のコールは左のようなもので、2番目のコールは右のものです。 dskToMv == 0のときに応じて、LLLRLLLRLLRLRLRLRLRLLLRRのようなものがあります。このようなものは順不同かもしれませんが、データ構造をどのようにトラバースしているかのためです。基本的にそれはあなたが望む/考えているものを数えていません。 – AbstractDissonance

0

静的変数を使用できます。 関数が(再帰的に)呼び出されるたびに、この変数をインクリメントします。

#include <iostream> 

void ToH(int dskToMv, int cLocation, string orpeg, int tmpLocation, string expeg, int fLocation, string depeg) 
{ 
    static int count=0 
    if(dskToMv != 0) 
    { 
     count++; 
     ToH(dskToMv-1, cLocation, orpeg, fLocation, depeg, tmpLocation, expeg); 
     cout<<"Step "<<count<<": Move one disk from the "<< orpeg << " to the " << depeg 
      << " " << cLocation << " -> " << fLocation << endl; 
     ToH(dskToMv-1, tmpLocation, expeg, cLocation, orpeg, fLocation, depeg); 
    } 
} 

int main() 
{ 
    int c; 
    cout << "Enter the number of disks: "; 
    cin >> c; 
    ToH(c, 1, "original peg ", 2, "extra peg", 3, "destination peg"); 
} 

ホープこれは

関連する問題