質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

マージ

複数のデータベースやファイル、プログラムなどを決まった手順や規則に従って一つに結合すること。

MinGW

MinGW(ミン・ジー・ダブリュー)は GNUツールチェーンのWindows移植版です。 ランタイムライブラリと開発ツールで構成されています。

Q&A

解決済

3回答

566閲覧

マージソートの入力がある数を越えると作動しなくなる。

Hinomae

総合スコア7

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

マージ

複数のデータベースやファイル、プログラムなどを決まった手順や規則に従って一つに結合すること。

MinGW

MinGW(ミン・ジー・ダブリュー)は GNUツールチェーンのWindows移植版です。 ランタイムライブラリと開発ツールで構成されています。

0グッド

0クリップ

投稿2020/11/04 14:07

要素の数を事前に指定し、1~20のいずれかで作られた数字列をマージソートするプログラムなのですが、要素数Nを173643以上の数とすると実行されず、コンパイラがフリーズしてしまいます。
環境はVisual Studio CodeとMinGWなのですが、何か対処法はありますでしょうか。

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <time.h> 4#define N 173642 5 6void Merge(int *S,int left,int right); 7void MergeSort(int *S,int left,int right); 8 9int main(void) 10{ 11 int i,S[N]; 12 long cpu_time; 13 14 srand((unsigned)time(NULL)); 15 for(i=0; i<N; ++i){ 16 S[i]=rand()%20+1; //1~20までの乱数生成 17 } 18 19 20 for(i=0; i<N; ++i){ 21 printf("%d ",S[i]); 22 } 23 24 printf("\n"); 25 26 cpu_time=clock(); 27 28 MergeSort(S,0,N-1); 29 30 for(i=0; i<N; ++i){ 31 printf("%d ",S[i]); 32 } 33 34 printf("\nN=%d,CPU Time: %.4f [sec]\n",N,(double)(clock()-cpu_time)/CLOCKS_PER_SEC); 35 36 return 0; 37} 38 39void MergeSort(int *S,int left,int right) 40{ 41 int mid; 42 43 mid=(left+right)/2; 44 45 if(left<right){ //配列の要素数が2以上のとき 46 MergeSort(S,left,mid); 47 MergeSort(S,mid+1,right); 48 Merge(S,left,right); 49 } 50} 51 52void Merge(int *S,int left,int right) 53{ 54 int i,mid,size_L,size_R; 55 int j=1,k=1; 56 int L[N],R[N]; 57 58 mid=(left+right)/2; 59 size_L=mid-left+1; //左側配列の大きさ 60 size_R=right-mid; //右側配列の大きさ 61 62 for(i=0; i<size_L; ++i){ 63 L[i]=S[left+i]; 64 } 65 66 for(i=0; i<size_R; ++i){ 67 R[i]=S[mid+i+1]; 68 } 69 70 for(i=1; i<=size_L+size_R; ++i){ 71 if(j>size_L){ 72 S[left+i-1]=R[k-1]; 73 ++k; 74 }else if(k>size_R){ 75 S[left+i-1]=L[j-1]; 76 ++j; 77 }else if(L[j-1]<R[k-1]){ 78 S[left+i-1]=L[j-1]; 79 ++j; 80 }else{ 81 S[left+i-1]=R[k-1]; 82 ++k; 83 } 84 } 85}

コンパイラの表示は以下のようになり、次の入力を促されてしまいます。


N=173642,CPU Time: 18.6740 [sec] //N=173642の場合実行可能
PS C:\programming> .\a.exe   //N=173643にすると実行されない

PS C:\programming>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

Merge内の配列LとRをmallocで動的に確保することで解決できました。
具体的に分析して対処法を上げて下さったkazuma-sさんをベストアンサーに選ばせて頂きます。

投稿2020/11/04 23:42

Hinomae

総合スコア7

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

sizeof(int) が 4 とすれば、
main の中の int S[N]; について、 sizeof(S) = 173642 x 4 = 694568バイト。
Merge の中の sizeof(L) と sizeof(R) も 694568バイト。
3つの合計で 2083704バイト。
Hinomaeさんの環境ではスタックサイズ 2MB に制限されていて、
他の変数も含めると、その合計で 2MB を超えてしまうのでしょう。
S も L も R も自動変数で関数に入るたびにスタック上に領域が確保されます。

main -> MergeSort -> MergeSort -> ... -> MergeSort -> Merge

MergeSort は再帰呼出しで 20回近く呼び出されますが、MergeSort 1つの変数の
サイズの合計は数10バイトなので、たいして問題になりません。

main と Merge で自動変数にしているのが良くないので、静的変数にしましょう。
static int S[N]; static int L[N], R[N]; のように書けばよいでしょう。

または、グローバル変数にすれば、静的変数になるので static は不要です。

投稿2020/11/04 17:37

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

MergeSortは再起関数になってて、実行されるたんびに、
int L[N],R[N];
がローカル変数で確保されるため、スタックがそれで食いつぶされるんでしょうね

投稿2020/11/04 14:41

y_waiwai

総合スコア87747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問