私は様々なディストリビューションでテストしていますが、逆順(降順)のソート済み配列が入力として与えられると、セグメンテーションフォルトが発生します。ときどき逆ソートされた配列でもうまく動作することがありますが、時には、特に大きな逆ソート配列(> 100000)でセグメント化エラーエラーが発生することがあります。再帰呼び出し深度の限界、再帰呼び出し深度の限界、再帰呼び出し深度の限界、再帰呼び出しの深さ、再帰呼び出しの深さ、再帰的プログラムを記述する際の予防措置について注意しなければならないことがあります。このコードでセグメンテーションフォルトが発生する理由を誰にでも教えてください
答えて
の値として、常にa[lower]
を使用する代わりに、upper
とlower
間のランダムな値を使用します。
逆順ソート配列は、パーティションスキームの最悪の場合です。n
要素の配列にn-1
回を繰り返し表示します。
この病理学的なケースを避けるためにパーティションスキームを試してみることはできますが、quick_sort
関数で深い再帰を避ける方法があります。病理学的症例は非常に遅いが、もはやクラッシュすることはない。
#include <stdio.h>
#include <time.h>
int partition(double *a, int lower, int upper) {
/* assuming lower < upper */
int i = lower, j = upper;
double t = a[lower], temp;
while (i <= j) {
while (i <= upper && a[i] <= t)
i++;
while (a[j] > t)
j--;
if (i < j) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
temp = a[lower];
a[lower] = a[j];
a[j] = temp;
return j;
}
void quick_sort(double *a, int lower, int upper) {
while (lower < upper) {
int j = partition(a, lower, upper);
if (j - lower < upper - j) {
if (lower < j - 1) {
quick_sort(a, lower, j - 1);
}
lower = j + 1;
} else {
if (j + 1 < upper) {
quick_sort(a, j + 1, upper);
}
upper = j - 1;
}
}
}
int main(void) {
double a[65536];
for (int n = 2; n <= (int)(sizeof(a)/sizeof(*a)); n += n) {
for (int i = 0; i < n; i++) {
a[i] = n - i;
}
clock_t t = clock();
quick_sort(a, 0, n - 1);
t = clock() - t;
for (int i = 1; i < n; i++) {
if (a[i - 1] > a[i]) {
printf("out of order at %d: %f > %f\n", i - 1, a[i - 1], a[i]);
return 1;
}
}
printf("a[%d] sorted in %.3f msec\n", n, (double)t * 1000.0/CLOCKS_PER_SEC);
}
return 0;
}
出力:ここ
がコードである
a[2] sorted in 0.002 msec
a[4] sorted in 0.001 msec
a[8] sorted in 0.001 msec
a[16] sorted in 0.001 msec
a[32] sorted in 0.000 msec
a[64] sorted in 0.002 msec
a[128] sorted in 0.006 msec
a[256] sorted in 0.021 msec
a[512] sorted in 0.074 msec
a[1024] sorted in 0.287 msec
a[2048] sorted in 1.185 msec
a[4096] sorted in 5.104 msec
a[8192] sorted in 19.497 msec
a[16384] sorted in 78.140 msec
a[32768] sorted in 297.297 msec
a[65536] sorted in 1175.032 msec
はあなたの2番目の質問、に関してはどのような要因には依存して再帰的なプログラムを書きながら撮影するために必要なものを予防策のでしょうか?スタック空間上の
制限されている実装固有の(ような概念がある場合)、異なるシステムは非常に異なる制限があります:小型組み込みシステム上のわずか数キロバイトから数メガバイトに決定的な答えはありません大規模なシステムでは
何千回も繰り返すことは危険であり、自動ストレージを備えた大規模なアレイもそうです。上記のコードでは、64K doubleの配列を定義していますが、これは現代の汎用コンピュータでは問題ではありませんが、小さなデジタルセンサーでは多すぎる可能性があります。より小さい半分のアプローチでのの繰り返しの最大再帰レベルは、log(N)(
N=65536
の場合は16
)であり、すべてのシステムでOKである必要があります。
はい、セグメント化はあまりにも深い再帰のためです。あなたが速いあなたの関数でソートする逆配列を持っている場合は、必ずtの値としてa[lower]
を使用するよう
は、partation
機能でt
は常にレルム内最大または最小値になります。つまり、戻り値がpartation
の場合は、配列が逆転したときに常にupper
または 'lower'に等しくなります。これにより、(上位 - 下位)再帰の総数が発生し、必ずエラーが発生します。これを避けるために、あなたが原因スタックオーバーフローのセグメンテーションフォールトを持ってt
#include <stdlib.h>
#include <time.h>
int partation(double *a, int lower, int upper)
{
int i = lower, j = upper;
double t = a[rand() % (upper - lower) + lower], temp;
while (i <= j)
{
while (i <= upper&&a[i] <= t) i++;
while (a[j]>t) j--;
if (i <= j)
{
temp = a[i]; a[i] = a[j]; a[j] = temp;
}
}
temp = a[lower];
a[lower] = a[j];
a[j] = temp;
return j;
}
void quick_sort(double *a, int lower, int upper)
{
int j;
if (lower >= upper) return;
else
{
j = partation(a, lower, upper);
quick_sort(a, lower, j - 1);
quick_sort(a, j + 1, upper);
}
}
int main()
{
srand(time(0));
/*input the value of a here*/
/*double a[10000];
for (int i = 10000 - 1, index = 0; --i;++index)
{
a[index] = i;
}*/
quick_sort(a, 0, 9999);
return 0;
}
これは、再帰呼び出しの深さが大きいためです。再帰的な呼び出しの深さの限界、それが依存する要因、再帰的なプログラムを書くときに注意する必要があることについて、スタックのオーバーフローを意味しますか?私はプログラミングの初心者です。これについて私に説明してください。 –
それはプログラムによって使用可能なスタックサイズに依存するので、実際にはコンピュータと構成によって異なります。再帰回数が500回を超える場合は注意が必要だと私は個人的に言っています。通常、深い再帰(ループなどを使用して)を避ける方法があります。 – leyanpan
- 1. 誰でもGNU Octaveでこのエラーが発生する理由を教えてください。
- 2. 誰でもこのhamlコードに何も表示されない理由を教えてください。
- 3. iPhone 5でこのコードがクラッシュする理由を教えてください。
- 4. 誰かがこのapache設定が404の結果をもたらす理由を教えてください。
- 5. 誰でも次のPHPコードでクエリが実行されない理由を教えてもらえますか?
- 6. 誰も私のjsコードがjsfiddleで動作していない理由を教えてもらえますか?
- 7. 誰でもこのコードを教えてもらえますか?
- 8. 誰でもjQueryセレクタを教えてください。
- 9. このGUIDが有効でない理由を教えてください。
- 10. 誰にでも、なぜこのことが起こっているのか教えてください。
- 11. 誰も私にエラーがある理由を教えてもらえますか?
- 12. Rails ActionMailerが本番環境でルーティングエラーを発生させる理由を教えてください。
- 13. 誰でも私のHTMLセクションがオーバーレイされている理由を教えてもらえますか?
- 14. 誰かがこのコードが動かない理由を教えてもらえますか?
- 15. 誰かがこのバッチスクリプトがうまくいかない理由を教えてもらえますか?
- 16. 誰かがこのラムダソート式がうまくいかない理由を教えてもらえますか?
- 17. 誰でもora-00904のエラーが表示される理由を教えていただけますか?
- 18. 試験紙がここに求めていることは誰でも教えてください。
- 19. FederatedAuthentication.SessionAuthenticationModuleをNULLに戻す理由を教えてください。
- 20. 誰かがこのコードの論理エラーを教えてもらえますか?
- 21. jQueryの:最後のセレクタは、それが動作しない理由を誰もが私に教えてくださいすることができます
- 22. 誰でも下のコードスニペットの出力がX88である理由を教えていただけますか?
- 23. このdatepickerが動作しない理由を教えてください。
- 24. 誰も私はこのグリッドCSSが動作していない理由を教えてもらえますか?
- 25. webpackローダーが "module.exports = ..."で返される理由を教えてください。
- 26. UIAlertViewでMonoTouchランタイムがクラッシュする理由を教えてください。
- 27. 誰かがこのjavascript関数が実行されない理由を教えてもらえますか?
- 28. 誰も私のナビゲーションがうまくいかない理由を教えてもらえますか?
- 29. 誰かが私にこの悪意を持っている理由を教えてもらえますか?
- 30. 誰もこのコードで何がうまくいかなかったか教えていただけますか?
時間 'gdb'を使用する方法を学ぶために、'ここに負になることができますjのように見えますが([J]>トン)J - ;私はjは最初のように負になることができるとは思わない ' –
要素がピボットとして選択されるので、このループの最初の要素よりも下に行くことはできません。while(a [j]> t)j--; jが最初のインデックスに減少したときに必ず終了してください。 –