• 締切済み

C言語のアルゴリズム、マージソートについて質問です。

C言語のアルゴリズム、マージソートについて質問です。 例えば下のプログラム #include <stdio.h> void merge(int first, int last, int *data, int *work); int main(void) { int data[9] = {1,8,3,6,5,4,7,2}; int work[9]; int i; merge(0,8,data,work); for(i = 0;i < 9;i++) printf("%d",data[i]); return 0; } void merge(int first, int last, int *data, int *work) { int middle, mae, ato, i; if (first == last) { return; } middle = (first + last) / 2; merge(first, middle, data, work); merge(middle + 1, last, data, work); i = first; mae = first; ato = middle + 1; while (mae <= middle && ato <= last) { if (data[mae] <= data[ato]) { work[i] = data[mae]; i++; mae++; } else { work[i] = data[ato]; i++; ato++; } } while (mae <= middle) { work[i] = data[mae]; i++; mae++; } while (ato <= last) { work[i] = data[ato]; i++; ato++; } for (i = first; i <= last; i++) { data[i] = work[i]; } } まずfirst=0,last=8でmerge関数に入り関数内8行目でmiddle=4となり、 10行目でfirst=0,last=4でmergeに入り同じく8行目でmiddle=2となり、 同じく10行目でfirst=0,last=2でmergeに入り同じく8行目でmiddle=1となり、 同じく10行目でfirst=0,last=1でmergeに入り同じく8行目でmiddle=0となり、 同じく10行目でfirst=0,last=0でmergeに入り3行目のifでreturnします。 そして前回のfirst=0,last=1,middle=0のmerge10行目に戻り, 12行目でfirst=1,last=1でmergeに入り3行目のifでreturnし、 12行目以下の作業をします。 そのまま一番下までいったあとはどうなるのでしょうか? また上で書いた手順もあっている自信はあまりないので ご指摘お願いします。

みんなの回答

回答No.5

#3です。まず、字数の関係で載せられなかった実行結果を示しておきます。 ----- 実行結果 ----- first=0 last= 7 middle= 3 first=0 last= 3 middle= 1 first=0 last= 1 middle= 0 first=0 last= 0 ...return first=1 last= 1 ...return merging 0 1 (case middle 0 [0 - 1]) first=2 last= 3 middle= 2 first=2 last= 2 ...return first=3 last= 3 ...return merging 2 3 (case middle 2 [2 - 3]) merging 0 2 (case middle 1 [0 - 3]) first=4 last= 7 middle= 5 first=4 last= 5 middle= 4 first=4 last= 4 ...return first=5 last= 5 ...return merging 4 5 (case middle 4 [4 - 5]) first=6 last= 7 middle= 6 first=6 last= 6 ...return first=7 last= 7 ...return merging 6 7 (case middle 6 [6 - 7]) merging 4 6 (case middle 5 [4 - 7]) merging 0 4 (case middle 3 [0 - 7]) Result: 1 2 3 4 5 6 7 8 答えは、肝心の境界値があなたの質問と異なっています。 答えは http://www.codereading.com/algo_and_ds/algo/merge_sort.html の通り、 first=1,last=1でdata[0-1]間のmergeに入り3行目のifでreturnし、 12行目以下の作業、すなわち mergingを行います。 そのまま一番下にいったあとは、次の配列data[2-3]について同じ操作を繰り返します。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.4

>インデントをつけられてはいかがでしょうか ここの掲示板は、インデントを無視してしまうのです。 残念なことに。

回答No.3

データ数と出力 for() の内容があっていませんが、プログラム間違ってません? 以下のプログラムを実行してみると、再帰ゆえ、あなたが答えるほど内容は簡単ではないようです。 http://www.codereading.com/algo_and_ds/algo/merge_sort.html #include <stdio.h> #define KOSU 8 void merge(int, int, int *, int *); int main(void) { int data[KOSU] = {1,8,3,6,5,4,7,2}; int work[KOSU]; int i; merge(0,KOSU-1,data,work); printf("Result:\n"); for(i = 0; i < KOSU; i++) printf("%d ",data[i]); printf("\n"); return 0; } void merge(int first, int last, int *data, int *work) { int middle, mae, ato, i; printf("\tfirst=%d \tlast= %d ", first, last); if (first == last) { printf("\t...return\n"); return; } middle = (first + last) / 2; printf("\tmiddle= %d\n", middle); merge(first, middle, data, work); merge(middle + 1, last, data, work); i = mae = first; ato = middle + 1; printf("\tmerging %d %d (case middle %d [%d - %d])\n", mae, ato, middle, first, last); while (mae <= middle && ato <= last) { if (data[mae] <= data[ato]) work[i++] = data[mae++]; else work[i++] = data[ato++]; } while (mae <= middle) work[i++] = data[mae++]; while (ato <= last) work[i++] = data[ato++]; for (i = first; i <= last; i++) data[i] = work[i]; }

  • ohtawa
  • ベストアンサー率23% (9/38)
回答No.2

どうなるでしょうかって 実行させてみればよいではありませんか それから ソースがよみづらいです インデントをつけられてはいかがでしょうか 途中の過程を追いかけたかったら デバッグツールを使うのも一法かと

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「一番下」というのが「関数の終わりの }」のことであれば, そこまでいったら自動的に return します.

関連するQ&A

  • マージソート

    マージソートの実行時間を測定するプログラムを書いています。 コンパイルの時にはエラーが出ないのですが、実行するとコマンドプロンプトが強制終了されます。 どこが悪いか、どう直せばいいのか指摘していただけないでしょうか? よろしくお願いします。 ~qtime.c~ //マージソート実行用プログラム //bcc32 mtime.c merge.c m1.c sfmt.c #include <stdio.h> #include <stdlib.h> #include <time.h> #include "sfmt.h" #define MAX 5000 void merge_sort(int a[], int start, int end); main() { int i , x[MAX] , n; time_t start , end ; int sn; printf("適当な数字の入力 : "); scanf("%d", sn); init_gen_rand(sn); for(i=0; i<MAX; i++) x[i]= (gen_rand32()% MAX);; n=MAX; start = clock(); //測定対象プログラム merge_sort(x, 0, n-1); end = clock(); printf("sort\n"); for(i =0 ; i < n ; i++ ) if ( i == i/100*100) printf("%d\n" , x[i]); printf ("実行時間: %f sec\n" , (double)(end-start) /CLOCKS_PER_SEC); return 0; } ~merge.c~ int b[100]; void merge_array(int x[], int start, int end) { int mid, i, j, k; mid = (start + end) /2; i = start; j = mid + 1; for(k = start; k <= end; k++){ if(x[i] > x[j] && j <= end || i > mid){ b[k] = x[j]; j++; } else{ b[k] = x[i]; i++; } } for(k = start; k <= end; k++){ x[k] = b[k]; } } ~m1.c~ void merge_array(int x[], int start, int end); void merge_sort(int a[], int start, int end); void merge_sort(int a[], int start, int end) { int mid; if(start >= end) return; mid = (start + end) / 2; merge_sort(a, start, mid); merge_sort(a, mid + 1, end); merge_array(a, start, end); }

  • C言語 シンプルソート

    C言語始めて1年の初心者です。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXSIZE 10000 void swapData(char *x, char *y); void simpleSort(char data[], int first, int last); int main(int argc, char *argv[]) { int data[MAXSIZE][300]; int i, j, count; FILE *fp; if(argc != 2) { fprintf(stderr, "Usage: %s <filename>\n", argv[0]); exit(0); } if ((fp = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "File %s is not found.\n", argv[1]); exit(0); } for(i = 0; i < MAXSIZE; i++) { if (fscanf(fp,"%s", &data[i]) == EOF) break; } simpleSort(data[], 0, i - 1); for(j = 0; j < i; j++) printf("%s\n", data[j]); } void swapData(char *x, char *y){ char tmp[300]; strcpy(tmp, x); strcpy(x, y); strcpy(y, tmp); } void simpleSort(char data[], int first, int last) { int i, j; for(i = first; i < last; i++){ for(j = i+1; j <= last; j++){ if(strcmp(&data[i], &data[j]) > 0) swapData(&data[i], &data[j]); } } } 読み込んだ文字データをシンプルソートするプログラムなんですが、コンパイルできません。 simpleSortの部分がおかしいみたいなんですが、見直しても先入観からか間違いを見つけられません・・・・ どなたか間違いを指摘していただけたら助かります。

  • C++でのマージソートの実現方法について

    C++でのマージソートの実現方法について、以下のコードを書いたのですが、どうしてもうまくソートできませんでした。 marge関数がおかしいと思うのですが、自分で確かめてみても、どこがおかしいのか分かりませんでした。 どなたか、どうすればソートされた結果がメイン関数で表示されるようにできるのか教えていただけないでしょうか? #include <iostream> #include <vector> using namespace std; class Array { private: vector<int> array; public: void insert( int value ){ array.push_back( value ); } int getSize( ){ return (int)array.size( ); } void marge_sort( ){ marge_sort( 0, (int)array.size( ) - 1 ); } void marge_sort( int left, int right ); void marge( int left, int middle, int right ); void print( ); }; // マージソートにより配列の添字 left ~ right の部分を整列する関数 void Array::marge_sort( int left, int right ){ if( left >= right ) { return; } int middle = (left + right) / 2; //中央の添字を求める marge_sort( left, middle ); //左の要素が全てバラバラになるまで marge_sort( middle + 1 , right ); //右の要素が全てバラバラになるまで marge( left, middle, right ); //バラバラの要素をソートして併合 } // 個別にソートされた2つの配列(添字 left ~ middle と添字 middle+1 ~ right)を作業用配列を使ってマージする関数 void Array::marge( int left, int middle, int right ) { int num=right-left; int *tmp=new int[num]; int t=0,l=left,r=middle; while(l<middle&&r<right){ if(array[l]<=array[r]){ tmp[t++]=array[l++]; } else { tmp[t++]=array[r++]; } } while(l<middle){ tmp[t++]=array[l++]; } while(r<right){ tmp[t++]=array[r++]; } for(int i=0;i<num;i++){ array[left+i]=tmp[i]; } delete tmp; } // 配列の内容を表示する関数 void Array::print( ) { for ( int i = 0; i < (int)array.size( ); i++ ) { cout << array[i] << " "; } cout << endl; } int main( ) { Array a1; a1.insert( 56 ); a1.insert( 34 ); a1.insert( 57 ); a1.insert( 64 ); a1.insert( 3 ); a1.insert( 87 ); a1.insert( 85 ); a1.insert( 37 ); a1.insert( 21 ); a1.insert( 4 ); a1.insert( 68 ); a1.insert( 62 ); a1.insert( 42 ); a1.insert( 55 ); a1.insert( 63 ); a1.insert( 95 ); a1.insert( 7 ); a1.insert( 32 ); a1.insert( 78 ); a1.insert( 11 ); cout << "要素数: " << a1.getSize( ) << endl; cout << "ソート前: "; a1.print( ); a1.marge_sort(); // ここで,ソートを行う関数を呼び出す cout << "ソート後: "; a1.print( ); return 0; } // 実行結果 要素数: 20 ソート前: 56 34 57 64 3 87 85 37 21 4 68 62 42 55 63 95 7 32 78 11 ソート後: 3 4 34 37 21 42 55 56 57 62 63 7 32 64 68 78 85 87 95 11 ↑のソート後の表示が、昇順にソートされるようにしたいのです。

  • C言語 探索に関して

    C言語探索プログラムについて質問です。 #include <stdio.h> #define MAXSIZE 100 void swapData(int *x, int *y){ int tmp; tmp = *x; *x = *y; *y = tmp; } void simpleSort(int data[], int first, int last) { int i, j; for(i = first; i < last; i++){ for(j = i+1; j <= last; j++){ if(data[i] > data[j]) { swapData(&data[i], &data[j]); } } } } int ArrayBinarySearch(int data[], int n, int x) { int left = 0, right = n - 1, center; while(left <= right){ center = (left + right)/2; if(data[center]=x){ return center; }else if(x > data[center]){ left = center + 1; }else if(x < data[center]){ right = center - 1; } } return -1; } int main(int argc, char *argv[]) { int data[MAXSIZE]; int i, x; FILE *fp; scanf("%d", &x); fp = fopen(argv[1], "r"); for(i = 0; i < MAXSIZE; i++) { if (fscanf(fp,"%d", &data[i]) == EOF) break; } simpleSort(data, 0, i-1); printf("%d", ArrayBinarySearch(data, i, x )); return 0; } 数値が書かれたファイルを読み込んでソートした後に二分探索を行うプログラムをつくったのですが、うまく動きません。 どこがおかしいか教えてください。 お願いいたします。 ちなみに関数ArrayBinarySearchは目的の値が見つかれば配列中でのインデックスを、見つからない場合は-1を返す関数にしているつもりです。

  • C言語

    3. 整数配列data の,data[left]からdata[right-1]の最小値がある添字番号を返す関数 int min_ind_ary(const int data[ ], int left, int right) で最小値が複数あるときは,一番小さい添字を返すようにするにはどうしたらよいのかわかりません? 途中経過↓ #include <stdio.h> int min_ind_ary(const int data[10],int left,int right) { int i,min = 0; for( i = 1; i < left; i++){ if(data[min] < data[i]) min = i; } return min; } void print_ary(const int data[10], int size){ int i; for(i = 0; i < 10; i++){ printf("%2d", data[i]); } } void sort_ary (int data[10], int size) { int i; for(i = 0; i < size - 1; i ++ ) { int min, work; min = min_ind_ary(data, i, size); work = data[min]; data[min] = data[i]; data[i] = work; } return; } int main(void) { int data[10] = {1, 6, 4, 8, 2, 3, 5, 9, 7, 4}; print_ary(data, 10); sort_ary(data, 10); print_ary(data, 10); return 0; }

  • マージソートについて。

    マージソートについて勉強しており、プログラムを作ってみたのですが どうしてもcc=~~の箇所の数値がおかしく表示されてしまいます #include<stdio.h> int main(void) { int a[5]={20,40,15,35,50}; int b[3]={55,20,65}; int c[8]; int i,z,k; printf("a="); for(i=0;i<5;i++) { printf("%d ",a[i]); } printf("\nb="); for(z=0;z<3;z++) { printf("%d ",b[z]); } while(i <= 5 && z <= 3){ if(i < z){ a[i]=c[k]; i++; } else if(i > z){ b[z]=c[k]; z++; } } while(i<5 && z<3) { i=k; i++; z=k; z++; } printf("\nc=") ; for(k=0;k<8;k++) { printf("%d ",c[k]); } return 0; } ご教授していただければ幸いです。

  • マージソートについて

    マージソートの要素の比較と交換回数を計測するプログラムを作っているのですが、マージのどの段階が交換処理になるのかが分からず困っています。 マージ処理の実行回数をカウントする配列sを設けて処理をカウントする場合、以下のプログラムだとどのタイミングでカウントすればよいでしょうか? ちなみに配列aは初めに値を割り振った配列で、配列bは別途で用意した作業用配列です。 最後のfor文やif文付近で配列の値を変化させて計測してみたのですが、計算量に合った動きをしてくれませんorz void merge_sort(int a[], int low, int high){ int mid, i, j, k; if(low >= high) return; mid = (low + high)/2; merge_sort(a, low, mid); merge_sort(a, mid+1, high); for(i = low; i <= mid; i++) b[i] = a[i]; for(i = mid+1, j=high; i <= high; i++, j--) b[i] = a[j]; i = low; j = high; for(k = low; k <= high; k++){ if(b[i] <= b[j]){ a[k] = b [i++]; } else{ a[k] = b[j--]; } } }

  • マージソートのプログラム

    ↓が自分の作ったマージソートのプログラムなのですが、コンパイルするとエラーが起きてしまいます。 mergesort()にポインタを引数として渡してる、引数の数が足りない、ということが書いてありますが…。 ちゃんとint型を渡してるし、引数の数も合ってるように思います。 どこがおかしいのでしょう? #include<stdio.h> #include<stdlib.h> #include<time.h> #define Max 255 int A[Max]; main(){ int n,k; n=inputdata(); int w=1; mergesort(w,n); printdata(n); return(0); } inputdata(){ //配列に乱数を要素として入れていく int n,i; printf("n= "); scanf("%d",&n); //使用者にいくつの要素を入れるか指定してもらう srand(time(NULL)); for(i=1; i<=n; i++){ A[i]=1+rand()%30; } printf("A[%d]={%d,",n,A[1]); for(i=2;i<n;i++) printf("%d,",A[i]); printf("%d}\n",A[n]); return(n); } void mergesort(int p, int r){ int q; if(p<r){ q=(p+r)/2; mergesort(p,q); mergesort(q+1,r); merge(p,q,r); } } void merge(int p, int q, int r){ int i,j,k,B[Max]; i=p; j=q+1; for(k=p;k<=r;k++){ if((j>r) || ((i<=q)&&(A[i]<=A[j]))){ B[k]=A[i]; i++; }else{ B[k]=A[j]; j++; } } for(k=p; k<=r; k++) A[k]=B[k]; } printdata(int n){ int i; printf("A[%d]={%d,",n,A[1]); for(i=2; i<n; i++) printf("%d,",A[i]); printf("%d}\n",A[n]); } ・エラーメッセージ merge1.c: In function ‘main’: merge1.c:12: warning: passing argument 1 of ‘mergesort’ makes pointer from integer without a cast merge1.c:12: error: too few arguments to function ‘mergesort’ merge1.c: At top level: merge1.c:31: error: conflicting types for ‘mergesort’ /usr/include/stdlib.h:294: error: previous declaration of ‘mergesort’ was here merge1.c:41: warning: conflicting types for ‘merge’ merge1.c:37: warning: previous implicit declaration of ‘merge’ was here

  • クイックソート(C言語)

    こんにちは<_ _> クイックソートについての質問です。 左端を軸にクイックソートでデータを昇順にソートする プログラムを作ったのですがうまく動きません #include<stdio.h> void quick(int *,int,int); #define N 10 int main(void) { static int a[]={41,24,76,11,45,64,21,69,19,36}; int k,b=0; quick(a,0,N-1); for(k=0;k<N;k++) printf(" %d",a[k]); return 0; } void quick(int a[],int left,int right) { int s,t,i,j; t=right; i=left+1; j=a[left]; if(right>left){ while(1){ while(a[++i]>j); while(a[--t]<j && t>0); if(i>=t){ break; } s=a[i]; a[i]=a[t]; a[t]=s; } s=a[i]; a[i]=j; a[left]=s; quick(a,left,t-1); quick(a,t+1,right); } } 値の入れ替え、軸の入れ替えもしましたが結果として 「41 41 76 69 45 64 41 19 0 36」 このような結果で出力されてしまいます・・・ 時間に余裕のある方いましたらご指導をお願いします。 よろしくお願いします。<_ _>

  • 画面に表示させたいのですが

    ランダムで生成した数字をソートするプログラムを作っています。 ソートした結果を画面に表示させたいのですが、 うまくいかず困ってます。 どなたかアドバイスください。 下はソートまでのプログラムです #include<stdio.h> #include<stdlib.h> static int *data = NULL,*work; static int datasize; void merge_vec(int *a,int sa,int *b,int sb){ int c,*p = work; for(c=0;c<sa;c++) work[c]=a[c]; while(sa&&sb){ if(*p <= *b){ *a++ = *p++; sa--; }else{ *a++ = *b++; sb--; } } while(sa--){ *a++ = *p++; } } int merge_aux(int a[],int size){ int j; switch(size){ case 0 : case 1 : return(0); case 2 : if(a[0] > a[1]){ j = a[0]; a[0] = a[1]; a[1] = j; } break; default : j = size / 2; merge_aux(a,j); merge_aux(a+j,size-j); merge_vec(a,j,a+j,size-j); } return 0; } int merge(int p[],int size){ int j=1,c; if(size <= 2){ return merge_aux(p,size); } work = malloc(size * sizeof(int)); if(work == NULL) exit(2); merge_aux(p,size); free(work); return 0; } void make_data(int s,int n){ int i,*p; srand(s); p = malloc(n * sizeof(int)); if(p == NULL) exit(1); for(i = 0; i < n; i++) p[i] = rand(); data = p; datasize = n; } int print_data(void){ int *p = data; int n = datasize; printf("作られた乱数は\n"); while(n--){ printf("%d\n",*p++); } } int get_int(void) { int n; printf("作成する整数の数をを入力してください : "); scanf("%d", &n); return n; } int main(void){ int n,i; printf("乱数を生成します"); n = get_int(); if(data != NULL) free(data); make_data(2008,n); print_data(); merge(data,n); return 0; }

専門家に質問してみよう