• 締切済み

シェルソートのプログラムが分かりません

教科書どおり下のようなプログラムを作ったのですが、ちゃんとソートされません。 打ち間違いなどを探しているのですが見つからないんです・・・ それと、プログラム11行目のj=j-hが何のためにあるのか分かりません。もしかしたら幼稚な質問かもしれませんがどうかよろしくお願いします。 #include<stdio.h> void shell(int n,int a[]) { int i,j,x,h; h=n/2; while(h<0) { for(i=h;i<=n;i++) { x=a[i]; for(j=i-h;j>=0;j=j-h) { if(a[j]>x) { a[j]=a[j+h]; a[j+h]=x; } } } h=h/2; } } main() { int a[]={30,20,60,29,10,90}; int n=6; int i; shell(n,a); for(i=0;i<n;i++) { printf("%4d",a[i]); } printf("\n"); }

みんなの回答

noname#50176
noname#50176
回答No.4

No.3 です。 <訂正> for(i=h;i<=n;i++) は、 for(i=h;n-i;i++) です。 インクリメントですので for(i=h;i<n;i++) でなくてもいく訳です。

noname#50176
noname#50176
回答No.3

勉強なさっているようなので、 以下も参考になさってみてください。 http://oshiete.nikkeibp.co.jp/qa3323110.html この No.3 の回答(私ですが…)の例を理解してみてください。 これは寄り道再帰と言う方法を使ったシェルソートです。 初見では分け解からないかもしれませんが、 ゆっくりと辿れば解かると思います。 尚、この寄り道再帰はゲームプログラムで非常に役立つので 参考になさってみて下さい。

noname#50176
noname#50176
回答No.2

以下が正解かと思います。 #include<stdio.h> void shell(int n,int a[]) { int i,j,x,h; h=n/2; while(h>0) { for(i=h;i<=n;i++) { for(j=i-h;j>=0;j=j-h) { x=a[j]; if(x>a[j+h]) { a[j]=a[j+h]; a[j+h]=x; } } } h=h/2; } } ≪説明≫ while(h<0) となっていましたがこれではグループ数に関わらず無条件で ロジックスルー(目的処理しない)してしまいます。 つまりこの場合グループ数が、 {3>1(3/2=1.5の切捨て)>0(1/2=0.5の切捨て)} ですから0以上の間、つまり while(h>0) です。 x=a[i]; for(j=i-h;j>=0;j=j-h) { if(a[j]>x) { a[j]=a[j+h]; a[j+h]=x; これでは要素を比較して入れ替える際に左側要素を壊してしまいます。 x=a[i]; がループ中に常時評価されると必ず a[i] が代入される のでデータが上書きされてしまいます。 したがって x=a[j]; if(x>a[j+h]) { a[j]=a[j+h]; a[j+h]=x; にすることでループ中に評価されたもの同士を入れ替えます。 for(j=i-h;j>=0;j=j-h) についてですが 例えば流れとして A,B,C,D,E,F,G,H,I,J の10個を以下のようにします。 グループ数:5(10/2)※間隔はグループ数-1となる AとF,BとG,CとH… このときは各1回でいいのですがグループ数が2になったとき、 AとC,CとE,EとG,GとI のように4回ループします。 この時、j=比較元位置 h=グループ数 ですから G(位置:7)から、j=j-h で 7-2=5 つまり次の対照の E(位置:5) が算出できたわけです。

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

> while(h<0) > { > for(i=h;i<=n;i++) ざっと見ただけですけれど、上に引用した3行のうち、 ・1行目の不等号の向きは正しいですか? ・3行目の、for文の継続条件に等号は必要ですか? 教科書に書いてあるコードをもう一度確認してみてはいかがでしょうか。

関連するQ&A

  • n個の要素を持つ配列xをシェルソートで昇順に整列

    穴埋め問題ですが、for文の j -= k の考えで立ち止まります。 #include <stdio.h> #define swap(X, Y) 【 1 】 ← X ^= Y, Y ^= X, X ^= Y void shell(int x[ ], int n); void main() {     int x[12] = {23, 67, 54, 82, 13, 28, 55, 61, 50, 32, 29, 44};     int n = 12, i ;     printf("配列(整列前)x => ");     for( i = 0; i < n - 1; i++ )         printf("%d, ",x[ i ]);     printf("%d\n",x[ i ]);       shell(x, n);     printf("配列(整列後)x => ");     for( i = 0; i < n - 1; i++ )         printf("%d, ",x[ i ]);     printf("%d\n",x[ i ]); } void shell(int x[ ], int n) {     int i, j, k = n ;     while( 【 2 】 ){ ← k > 0         【 3 】 ← k /= 2;         for( i = 0; 【 4 】; i++)             for( j = i; 【 5 】; j -= k)               swap(x[j], x[j + k]);     } } 【 1 】【 2 】は自信があるのですが【 3 】はあまり自信がないです。 【 4 】と【 5 】はどうすれば出来ますか教えてください。お願いします。

  • ソートプログラム

    ファイルから10個の整数が 29 45 11 2 86 91 33 62 77 59 のように一行に1個の形式で格納されている。このファイルから10個の整数を読み込み、選択法でソートし、この数字を小さい順に表示するプログラムを作成したのですが、ソート部分がうまくできません。どなたかどうすれば改善できるか教えてください。 <プログラム> #include<stdio.h> #include<stdlib.h> #define MAXN 100 int A[MAXN]; main() { _inputdata(); _selectionsort(1,10); _printdata(); } selectionsort(p,q) ___int p, q; { _int i, j, cmin, temp; _for(j = p; j <= q; j++){ __cmin = j; /* A[cmin]が現在の最小値 */ __for(i = j+1; i <= q; i++) ___if(A[cmin] > A[i]) cmin = i; __/* A[j]とA[cmin]との入れ換え操作 */ __swap(j, cmin); _} } swap(int x, int y) { _int temp; _temp = x; _x = y; _y = temp; } inputdata() { _FILE *fp; _if((fp=fopen("integers10.dat", "r"))==NULL) { __printf("ファイルが見つかりません: integers10.dat\n"); __exit(EXIT_FAILURE); _} _printf("データを入力\n"); _while(fscanf(fp, "%s", A)!=EOF) { ____printf("%s\n",A); _} _fclose(fp); } <コンパイル→実行> % gcc -o sort1 sort1.c % ./sort1 データを入力 29 45 11 2 86 91 33 62 77 59 ソート済みデータ 0 0 0 0 0 0 0 0 0 0 %

  • シェルソート(Cプログラミング)

    シェル・ソート 基本挿入法により、データを昇順にソートする。 というプログラムを実行したいと思ったのですが、エラーがでてしまいコンパイルできません。 書いたプログラムは以下の通りです。 #include<stdio.h> #include<math.h> #define N 100 int main (void) { int a[N],i,j,t; for (i=0;i<N;i++) a[i]=rand(); for (i=1;i<N;i++){ for (j=j-1;j>=0;j--){ if (a[j]>a[j+1]){ t=a[j]; a[j]=a[j+1]; a[j+1]=t; } else break; } } for (i=0;i<N;i++) printf("%8d",a[i]); } エラーメッセージは以下のようにでました。 警告 W8065 sample.c 10: プロトタイプ宣言のない関数 'rand' の呼び出し(関数 main ) 警告 W8070 sample.c 22: 関数は値を返すべき(関数 main ) どうすれば出来るのでしょうか、お答えよろしくお願いします。

  • クイックソートでの整列

    10個~20個程度の数列をキーボードから入力し、降順に整理し途中経過と整列後の状態を表示するプログラムを作りなさい。 このような課題が出ているのですが、よくわかりません。授業中に この2つのプログラムを応用すればできるといわれたプログラムがあるのですが、コンパイルするとエラーがたくさん出てきます。 ヒントを教えてください。 1.c #include <stdio.h> #include <stdlib.h> quick_sort(int a[], int l, int r); main(int argc, char *argv) { int i, x[100], n; n = atoi(argv[1]); for(i = 0;i< n;i++); scanf("%d", %x[i]); quick_sort(x, n); printf("sort\n"); for(i = 0;i<n; i++){ printf("%d\n", x[i]); } return ; } 2.c quick_sort(int a[], int l, int r) { int v,i,j,t; if(r>1) { v=a[r]; i=l-1; j=r; while(1) { while(a[++i]<v); while(a[--j]>v) if(j==l)break; if(i>=j)break; t=a[i];a[i]=a[j];a[j]=t; } a[r]=a[i];a[i]=v; quick_sort(a,l,i-1); quick_sort(a,i+1,r); } }

  • 情報処理のバブルソートの問題について質問します。

    情報処理のバブルソートの問題について質問します。 #include <stdio.h> int main(void) { double x[5]={6.0, 9.0, 2.0, 10.0, 8.0}; int i,j; int n=5; double temp; /* 初期状態の表示 */ printf("並べ替え前の並びは以下の通り:\n"); for (i=0; i<n; i++) { printf("%f,\t",x[i]); } printf("\n"); for (i=0; i<n-1; i++) { for (j=i+1; j<n; j++) { if (x[j] > x[i]) { temp = x[i]; x[i]=x[j]; x[j]=temp; } } } printf("大きい順に並べ替えた結果は以下の通り:\n"); for (i=0; i<n; i++) { printf("%f,\t",x[i]); } printf("\n"); return 0; } というプログラムを用いて行ってみたのですが、 これは王様ソートというプログラムだと言われました。 どのように換えればバブルソートになるのでしょうか?

  • プログラム

    下のようなプログラムを作ったのですが、10進2進変換をj=n>>2&1の部分にあるようなビットシフトではなく、 for(i=1;i<8;i++){printf("bit[%d]=%d\n",i,n%2);n=n/2;}に変えて剰余計算で行うプログラムにしたいのですが、分かる方がいましたら教えて下さい。お願いします。 #include <stdio.h> int main(void) { int i,j,n; i=2; printf("数字を入力="); scanf("%d",&n); printf("Dec=%d\n",n); printf("heX=0x%x\n",n); j=n>>2&1; printf("bit[%d]=%d\n",i,j); return(0); }

  • クイックソートプログラムでセグメンテーション違反がでるのですが

    クイックソートのプログラムを作成したのですが、 実行するとセグメンテーション違反が発生して、上手くいきません。何処に原因があるのでしょうか? また、セグメンテーションン違反とはどういったころなのでしょうか? アドバイス宜しくお願いします。 #include <stdio.h> int quick_sort(int *a,int start,int end); int partition(int *a,int start,int end); main() { int n; int a[n]; int i; printf("ソートしたい要素の個数は?\n"); scanf("%d",&n); for(i=0;i<=n-1;i++) a[i]=0; for(i=0;i<=n-1;i++){ printf("%dのデータを入力してください。\n",i+1); scanf("%d",&a[i]); } printf("ソート前のデータは以下の通り\n"); for(i=0;i<=n-1;i++) printf("%d ",a[i]); quick_sort(*a,1,n-1); printf("ソート後のデータは以下の通り\n"); for(i=0;i<=n-1;i++) printf("%d ",a[i]); } int quick_sort(int *a,int start,int end) { int pivot; if(end-start>0){ pivot=partition(a,start,end); quick_sort(a,start,pivot-1); quick_sort(a,pivot+1,end); } } int partition(int *a,int start,int end) { int i,j,pivot,tmp; i=start-1; j=end; pivot=a[end]; while(1){ while(a[++i]<pivot); while(i<--j && a[j]>pivot); if(i>=j) break; tmp=a[i]; a[i]=a[j]; a[j]=tmp; } a[end]=a[i]; a[i]=pivot; return i; }

  • ソートプログラム

    前に質問したものです。慌てていたのですみません。 Cで書いた直接選択法です。 #include <stdio.h> #include <stdlib.h> #include <time.h> #define N 1000 void main( void ) { int min,s,t,i,j,k,a[N]; srand((unsigned int)time(NULL)); for(i=0;i<N;i++) a[i]=rand()%1000+1; for(j=0;j<i-1;j++){ min=a[j]; s=j; for(k=j+1;k<i;k++){ if(a[k]<min){ min=a[k]; s=k; } } t=a[j];a[j]=a[s];a[s]=t; for(s=0;s<i;s++) printf("%d,\t",a[s]); } } このプログラムを実行すると、1回ずつ入れ替えされたものが出力されます。 100回、200回、・・・と入れ替えを行った値を出力するには、どうすればよいでしょうか? ループを入れてみたりしてみましたが、、?? プログラムを再帰の方法をつかって書いたほうが、、、?? よろしくお願いします。

  • クイックソートの交換回数

    クイックソートを行うプログラムを書いています。 これを、比較回数と交換回数を表示できるように改良したいのですが、うまくいきません。カウントする場所は間違えてないと思うのですが、出力の場所が悪いせいか、大量の出力結果が表示されます。 うまく表示させる方法を教えてください。 ~time.c~ #include <stdio.h> #include <stdlib.h> #include <time.h> #include "sfmt.h" #define MAX 5000 void quick_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(); //測定対象プログラム quick_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; } ~quick.c~ #include <stdio.h> int hikaku = 0, koukan = 0; int divide_array(int x[], int start, int end) { int i, j, tmp; i = start; j = end -1; while(1){ while(x[i] < x[end])i++; hikaku++; //比較カウント while(x[j] > x[end] && j>i)j--; hikaku++; //比較カウント if(i >= j) break; tmp = x[i]; x[i] = x[j]; x[j] = tmp; koukan++; //交換カウント i++; j--; } tmp = x[i]; x[i] = x[end]; x[end] = tmp; printf("比較回数: %d\n", hikaku); printf("交換回数: %d\n", koukan); return i; } ~quick2.c~ int divide_array(int x[], int start, int end); void quick_sort(int a[], int start, int end); void quick_sort(int a[], int start, int end) { int s; if(start >= end) return; s = divide_array(a, start, end); quick_sort(a, start, s-1); quick_sort(a, s+1, end); }

  • ソート

    読み込むファイル(sample.txt)は、 2,jirou 5,gorou 4,shirou 1,tarou 6,mutsuo 3,saburou 下記の処理をします。 #include<stdio.h> #include<string.h> #define N 6 int sort1[N]; char sort2[N][30]; int BubbleSort(int data[N]) { int i,j,flag; do{ flag=0; for(i=0;i<N-1;i++) { if(data[i]>data[i+1]) { flag=1; j=data[i]; data[i]=data[i+1]; data[i+1]=j; } } } while(flag==1); return 0; } int main(void) { FILE *fpin; int id,h,k; printf("\n"); fpin=fopen("sample.txt","r"); if(fpin==NULL){ printf("ファイルをオープンできず!\n"); return 1; } for(k=0;k<N;k++) { h=fscanf(fpin,"%d,%s",&sort1[k],sort2[k]); if(h==EOF) break; printf("%d %s\n",sort1[k],sort2[k]); } printf("\n"); BubbleSort(sort1); for(k=0;k<N;k++) printf("%d %s\n",sort1[k],sort2[k]); return 0; } 実行結果は、 2 jirou 5 gorou 4 shirou 1 tarou 6 mutsuo 3 saburou 1 jirou 2 gorou 3 shirou 4 tarou 5 mutsuo 6 saburou 名前(sort2)もソートさせるには、どうすればいいか手ほどきをお願いします…

専門家に質問してみよう