• ベストアンサー

併合処理ソートについて

いつも大変お世話になっておりますm(_ _)m アルゴリズム初心者なのですが、併合処理ソートをC言語で自作しています。しかし途中で行き詰ってしまい困っております。 私が作成したコードは以下になります。 void merge(int D[], int left, int mid, int right) { int x, y, i, M[50000]; x=left; y=mid+1; for(i=0; i<=right-left; i=i+1){ if((x != mid+1)&&(y != right+1)) { if (D[x]<D[y]){ M[i]=D[x]; x=x+1; } else if (D[x]=D[y]){ M[i]=D[x]; x=x+1; i=i+1; M[i]=D[y]; y=y+1; } else { M[i]=D[y]; y=y+1; } } if(x == mid+1){ M[i]=D[y]; y=y+1; } if(y == right+1){ M[i]=D[x]; x=x+1; } } for(i=left; i<=right-left; i=i+1){ D[i]=M[i]; } } void mergesort(int D[], int left, int right) { int mid; if(left != right){ mid=(left+right)/2; if(left < mid) mergesort(D,left,mid); if(right > mid+1) mergesort(D,mid+1,right); merge(D,left,mid,right); } } 入力は五桁程度の正の整数の昇順並び替えで、↑のコードの中には 入力と出力に関するコードは含んでいません。入力出力部分に誤りはないと思われます。 出力しても正しく昇順に並んでくれません。。。 どなたかご教授ご指導お願い致しますm(_ _)m

質問者が選んだベストアンサー

  • ベストアンサー
  • goosyu
  • ベストアンサー率58% (36/62)
回答No.2

■構文上の問題点  【誤】  else if (D[x]=D[y]){  【正】  else if (D[x]==D[y]){ ■ロジック上の問題点  次の処理に前にxまたはyが更新されて,この処理に入るがiが更新されない為,M[i]の値が上書きされて破壊されます。  ☆continueとかelse句とかで解決出来ると思います。  if(x == mid+1){   M[i]=D[y];   y=y+1;  }  if(y == right+1){   M[i]=D[x];   x=x+1;  } たぶん,まだ問題があるかもしれませんが,あとは小さい要素数でトレースしてロジックの完成度を確認してみては。

electron77
質問者

お礼

皆さんありがとうございます。 お二人にご指摘して頂いたところを修正したところ、入力がそのまま出力されるようになりました。 修正したのは上から13行目からで、以下のように修正しました。 else if (D[x]==D[y]){ M[i]=D[x]; x=x+1; i=i+1; M[i]=D[y]; y=y+1; } else { M[i]=D[y]; y=y+1; } } if(x == mid+1){ M[i]=D[y]; y=y+1; } else{ M[i]=D[x]; x=x+1; } } また何かございましたらよろしくお願いしますm(_ _)m

その他の回答 (1)

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

あきらかにおかしいところが 1ヶ所. 最後に M[] から D[] へ戻すところが間違ってます.

関連するQ&A

  • マージソート内の再帰処理にすいて

    #include<stdio.h> #define MAX 4 int temp[MAX]; void marge(int num[],int left,int right) { int i,j,mid,k   if(left>=right)return; mid=(left+right)/2; marge(num,left,mid);//(1) maege(num,mid+1,right);//(2) for(i=left;i<=mid;i++) temp[i]=num[i]; for(i=mid+1,j=right;i<=right;i++,j--) temp[i]=num]j]; i=left; j=right; for(k=left;k<=right;k++) if(temp[i]<=temp[j]) num[k]=temp[i++]; else num[k]=temp[j--] } マージソート内はこういった関数を記述してエラーもでないのですが、(1)と(2)の処理がよくわかりません。 (1)は再帰的に処理していってif(left>=right)return;の条件を満たした場合に(2)の処理に入っていきますよね? その場合、(2)の処理を行う際に(1)が(2)の再帰より前に記述されているので(1)がまた処理されるのでしょうか? 一連の流れを(1)、(2)を使って表してほしいです。

  • マージソート

    マージソートの実行時間を測定するプログラムを書いています。 コンパイルの時にはエラーが出ないのですが、実行するとコマンドプロンプトが強制終了されます。 どこが悪いか、どう直せばいいのか指摘していただけないでしょうか? よろしくお願いします。 ~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); }

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

    ↓が自分の作ったマージソートのプログラムなのですが、コンパイルするとエラーが起きてしまいます。 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

  • クイックソートのアルゴリズム

    http://www1.cts.ne.jp/~clab/hsample/Sort/Sort9.html こちらにあったソースを改造しました。 #include <stdio.h> void QSort(int x[ ], int left, int right) {   int i, j, temp;   int pivot;   i = left;   j = right;   pivot = x[(left + right) / 2]; // 6,5,4,3 // pivot=4   while (1) {   while (x[i] <= pivot) i++; // サイトのソースは = が無かったから付けた // 2回目のループでは j=2   while (pivot < x[j]) j--; // 2回目のループで x[-1] を参照しませんか? // 初回ループで i=0, j=3   if (i >= j) break;   temp = x[i]; x[i] = x[j]; x[j] = temp; // 交換   i++; j--;   }   ShowData(x, 10); // 途中経過を表示   if (left < i - 1) QSort(x, left, i - 1);   if (j + 1 < right) QSort(x, j + 1, right); } void ShowData(int x[ ], int n) {   int i;   for (i = 0; i < n ; i++) printf("%d ", x[i]);   printf("\n"); } void main(void) {   int x[] = {6, 3, 1, 7, 0, 4, 8, 5, 2, 9};   int n = 10;   printf("ソート前:\n");   ShowData(x, n);   printf("ソート中:\n");   QSort(x, 0, n - 1);   printf("ソート後:\n");   ShowData(x, n); } テストデータが 6,5,4,3 だと、 2回目のループで x[-1] を参照しませんか? 今コンパイラが使えません。 教えてください。 それと、=を付けたんですが、付けないといけませんよね?

  • free関数で動作が止まる

    freeしようとすると止まってしまいます。(1) q4614822の質問では用意するサイズが間違っていると起こるらしいのですが、出力に問題はないようです。スタックトレースというものをやってみたいのですが、C言語でも出来ますか? もう1つ質問ですがmerge_sortをmerge-sortで宣言するとコンパイルが通らない理由をお教え下さい。(2) 出力結果(1) 42 33 78 19 46 63 25 11 54 17 11 17 19 25 33 42 46 54 63 78 ^C←ここで止まります。 出力結果(2) Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland main.c: エラー E2449 main.c 5: 'merge' のサイズが不明、あるいはゼロ エラー E2141 main.c 5: 宣言の構文エラー エラー E2356 main.c 6: 'merge' の再宣言で型が一致していない エラー E2344 main.c 5: 一つ前の 'merge' の定義位置 警告 W8065 main.c 15: プロトタイプ宣言のない関数 'sort' の呼び出し(関数 main ) 警告 W8019 main.c 15: コードは効果を持たない(関数 main ) エラー E2356 main.c 23: 'merge' の再宣言で型が一致していない エラー E2344 main.c 6: 一つ前の 'merge' の定義位置 エラー E2449 main.c 30: 'merge' のサイズが不明、あるいはゼロ エラー E2356 main.c 30: 'merge' の再宣言で型が一致していない エラー E2344 main.c 23: 一つ前の 'merge' の定義位置 エラー E2141 main.c 30: 宣言の構文エラー *** 10 errors in Compile *** #include<stdio.h> #include<stdlib.h> #define N 10 void merge_sort(int,int); void merge(int,int); int a[N]={42,33,78,19,46,63,25,11,54,17}; int *b; int main(){ int i=0; b=(int*)malloc(sizeof(int)*N); while(i<N)printf("%3d",a[i++]); printf("\n"); merge_sort(0,N-1); free(b); i=0; while(i<N)printf("%3d",a[i++]); printf("\n"); return 0; } void merge(int left,int right){ int half=(right+left-1)/2,i=left,j=half+1,k; for(k=0;k<left+right+1;k++){ if((i<=half)&&(a[i]<a[j]||j==right+1))b[left+k]=a[i++]; else b[left+k]=a[j++]; } } void merge_sort(int left,int right){ if(left<right){ int half,k; half=(right+left-1)/2; merge_sort(left,half); merge_sort(half+1,right); merge(left,right); for(k=left;k<=right;k++)a[k]=b[k]; } }

  • C言語のクイックソートについて

    下記のようなクイックソートのプログラムをコーディングしたのですが、比較回数・挿入回数・シフト回数をそれぞれ知りたいのですが、どこにそれぞれのカウンタを挿入すればよいでしょうか? よろしくお願いします。 void quick(int a[],int left,int right) int i; int pl=left; int pr=right; int pivot; int tmp; pivot=a[(pl+pr)/2]; do{ while(a[pl]<pivot) { pl++; } while(a[pr]>pivot) { pr--; } if(pl<=pr) { swap(&a[pl],&a[pr]); pl++; pr--; } } while(pl<=pr); if(left<pr) { quick(a,left,pr); } if(pl<right) { quick(a,pl,right); } } void swap(int *x,int *y) { int temp; temp=*x; *x=*y; *y=temp; }

  • クイックソート(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」 このような結果で出力されてしまいます・・・ 時間に余裕のある方いましたらご指導をお願いします。 よろしくお願いします。<_ _>

  • マージソートについて

    マージソートの要素の比較と交換回数を計測するプログラムを作っているのですが、マージのどの段階が交換処理になるのかが分からず困っています。 マージ処理の実行回数をカウントする配列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--]; } } }

  • クイックソートの解説頂けないでしょうか。

    C言語を始めたばかりのプログラマ見習いです。 クイックソートのトレースでつまっています。 下記プログラムにあたっているのですが、 どなたか解説頂けないでしょうか。 void q_sort(int d[],int left,int right) { int i=left; int j=right; int t; t=d[(i+j)/2]; while(i<j){ for(;t>d[i];i++) ; for(;t<d[j];j--) ; if(i<=j){ /*Swap*/ int t; t=d[i]; d[i]=d[j]; d[j]=t; i++; j--; } } if(left<j){ q_sort(d,left,j); } if(){ q_sort(d,i,right); } } 長い引用で申し訳ありません。 クイックソートの理論的な部分は理解しているつもりです (最初に基準値を置き、それより大きいもしくは小さい 値を左右に振り分ける→分割統治法で繰り返し、最終的に 値がソートされた状態になる)。 よく判らないのがwhile文の中、特に最初のfor文の 役割です。初期値が空文で、中身もなし・・・この文は なにをしているのでしょうか? ネット上で解説されているソースをのぞいてみましたが 少し形が違っていたので、できればこのプログラムを もとにアドバイス頂けないでしょうか。 それ以外の回答(参考URL等)でも嬉しいです。 どうぞ宜しくお願いします

  • ソートプログラムについて

    ソートプログラムとして以下のように作成しました。 int main( ) { int i, j, temp; int ten[10] = { 98,34,67,89,99,23,54,21,10,65 }; for (i=0; i< 9; i++) { for(j=i+1; j<10; j++) { if (ten[i] < ten[j]) { temp = ten[i]; ten[i] = ten[j]; ten[j] = temp; } } } for (i = 0; i < 10; i++) { printf("SORT[%d] = %d\n",i,ten[i]); } } このプログラムを昇順で同じ数字が入力された場合、出力表示として 例: SORT[1]=99 SORT[2]=98 SORT[2]=98 SORT[3]=89 SORT[4]=70 というようにしたいのですが、プログラムをどのように 書いていけば良いのかわかりません。 例のような出力にするにはどのようにすればいいのでしょうか 教えて下さい。

専門家に質問してみよう