• 締切済み

配列の中身を入れ替える方法を教えてください

配列の中身を入れ替える方法をどなたかおしえてください。下のプログラムはちゃんと実行されるんですが、いまいち納得できません。 特に・・・↓↓ void sort(int a[]) { int x,y,z,min; for(x=0;x<10;x++) { min=x; for(y=x;y<10;y++) { if(a[min]>a[y]) { min=y; } } z=a[min]; a[min]=a[x]; a[x]=z; } } 上の部分でなぜfor文を2回使うのか?2回目のfor文のところはなぜ y=xなのか?0ではいけないのか?よくわかりません。一番最後の入れ替え作業のところは納得できたんですが、for文のところがよくわからないのでどなたか分かる方教えてください! #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <time.h> void sort(int a[]) { int x,y,z,min; for(x=0;x<10;x++) { min=x; for(y=x;y<10;y++) { if(a[min]>a[y]) { min=y; } } z=a[min]; a[min]=a[x]; a[x]=z; } } int main(int argc, char* argv[]) { int a[10],b,c; srand((unsigned)time(NULL)); for(b=0;b<10;b++) { a[b]=rand(); c=a[b]; printf("a[%d]=%d\n",b,a[b]); } sort(a); for(b=0;b<10;b++) { printf("小さい順a[%d]=%d\n",b,a[b]); } return 0; }

みんなの回答

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.4

>いまいち納得できません。 ・10区画に仕切られた、左右に横長な箱の中に、1区画1個ずつ、大きさの不揃いなリンゴが入っています。 ・リンゴには、重さの書かれたシールが貼ってあります。 これを「軽い順」に左区画(一番目とします)から入れ替える、としましょう(最終結果:最も軽いリンゴが一番目の区画、最も重いリンゴが十番目の区画)。 (片手のみで・・)  1.「仮の最も軽い」リンゴとして、一番目の区画(のリンゴ)とします。  2.このリンゴより軽いものがあるか、二番目以降(◆)の区画に入っているリンゴ9つと比較します。  3.2.の途中で「仮の最も軽い」リンゴより軽いリンゴがあった場合、その区画を「メモ」します。  4.3.では、「仮の最も軽い」値も更新されます( a[ min ] )。  5.2~4で、「真に最も軽い」リンゴが入っている区画が確定します。  6.「真に最も軽い」リンゴを区画から出して、別途用意したお皿に置きます。  7.空になった区画に、当初一番目の区画に入っていたリンゴを入れます。  8.一番目の区画は空ですので、ここにお皿に待避した「真に最も軽い」リンゴを入れます。 ・これでようやく、「最も軽いリンゴが一番目の区画」ができました(ソート作業の1/10)。 ・次は、この「一番目の区画」に入った確定リンゴを除外し、二番目の区画以降を上の手順に準じて求めます。 void sort( int a[] ) {  int x, y, z, min;  for( x = 0; x < ( 10 - 1 ); x++ ){ // 9個まで確定すれば残り1つも確定    min = x;   // 1.    for( y = ( x + 1 ); y < 10; y++ ){  // 2.      if( a[ y ] < a[ min ] ) min = y;  // 3.4.5.    }    z = a[ min ];   // 6.「両手」が使えるシステムなら??    a[ min ] = a[ x ]; // 7.    a[ x ] = z;    // 8.  } } >上の部分でなぜ for文を2回使うのか?  ・「順位」の意味合いの for文と、「中身をサーチ」の意味合いの for文と考えれば・・。 >2回目の for文のところはなぜ y = x なのか?0ではいけないのか?  ・「確定」したものを除外しないと同じものが・・。 ← 2.◆  なお、上のソースのように、y = ( x + 1 ); が無駄がないかな。

回答No.3

> ソート済みの部分が最小値探索範囲に含まれてしまう ...ですね。失礼しました。

  • Werner
  • ベストアンサー率53% (395/735)
回答No.2

選択ソート(セレクションソート)のようなので下記ページを見てください。 アルゴリズムとデータ構造編 第3章 選択ソート http://www.geocities.jp/ky_webid/algorithm/003.html > 2回目のfor文のところはなぜy=xなのか?0ではいけないのか? すでにソート済みの部分が最小値探索範囲に含まれてしまうからです。 0にしてしまうとソートできません。

回答No.1

> 上の部分でなぜfor文を2回使うのか? 1回ではソートが完了しません。 > 2回目のfor文のところはなぜy=xなのか?0ではいけないのか? いけなくはありませんが、無駄です。 0~x-1まではすでにソートが終わってますから。

関連するQ&A

  • テーブル配列の中身、出力値

    お世話になっております。 C言語勉強中のものです。 一定のひもをランダムに切断し、その長さを測ろうと思っています。 前回アドバイスを頂き、ソートを使って書いてみたのですが、詰まる部分があったのでご指導いただきたいと思いました。 #include <stdlib.h> #include <string.h> #include <stdio.h> #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))   int GetRandom(int min, int max);   int compare_int(const void* a, const void* b);   int compare_str(const void* a, const void* b); int main(void) {   int int_table[] = {GetRandom(0,10000)};   int i;   qsort( int_table, ARRAY_SIZE(int_table), sizeof(int), compare_int );   for( i = 0; i < ARRAY_SIZE(int_table); ++i ) {     printf("%d\n",int_table[i] ); }   return 0; } int compare_int(const void* a, const void* b) {   return ( *(int*)a - *(int*)b ); } int GetRandom(int min, int max) {     return min + (int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } 【困っている箇所】 ・int int_table[]={} の中身に次のようなものを入れることで、ランダムに切ったひもを、ソートできると考えているのですが、その方法を色々ためしましたが上手くいきませんでした。このようなやり方で良いのか、その場合どのようにしたら良いか、また違うのかを教えていただきたいです。 for(i=0;i<10;i++) { printf("%d\n",GetRandom(0,10000)); } ・また最終的にソートしたものを比較させようと思っています。 「出力値を保存する方法」が分からないので教えて頂きたいです。 ----前回ご覧になってくださった方へ---- アドバイスありがとうございました。 まだ初心者ですが、色々ご教授下さるとうれしい限りです。

  • 配列のソート(昇順)

    最大で30個の整数データを入力し、それを大きい順に並べ替えるプログラムを1次元配列と繰り返し・if文を使って作成しなさい。 という問題で #include<stdio.h> main() { int a[30],x,y,z; printf("Seisu wo 30 ko Nyuryoku \n"); for(x=0;x<=29;x++) scanf("%d",&a[x]); printf("before sort...\n"); for(x=0;x<=29;x++) printf("%d ",a[x]); for(x=0;x<=28;x++) for(y=0;y<=28-x;y++) if(a[y]<a[y+1]) { z=a[y];a[y]=a[y+1];a[y+1]=z; } printf("\n after sort...\n"); for(x=0;x<=29;x++) printf("%d ",a[x]); } ここまで出来たのですが最大で30個ということなので(例)「10個の整数を入力して Z を入力したら終了」 としたいのですがどこをどのようにすればいいですか?

  • selection

    /*単純選択ソート*/ #include <stdio.h> #define swap(type, x, y) do {type t = x; x = y; y = t; } while (0) /*--- 単純選択ソート ---*/ void selection(int a[], int n) { int i, j; for (i = 0; i < n - 1; i++) { int min = i; for (j = i + 1; j < n; j++) if (a[j] < a[min]) min = j; swap(int, a[i], a[min]); } } int main(void) { int i; int x[7]; int nx = sizeof(x) / sizeof(x[0]); printf("%d個の整数を入力せよ。\n", nx); for (i = 0; i < nx; i++) { printf("x[%d] : ", i); scanf("%d", &x[i]); } selection(x, nx); /* 配列xを単純選択ソート */ puts("昇順にソートしました。"); for (i = 0; i < nx; i++) printf("x[%d] = %d\n", i, x[i]); return (0); } をswapなしで書き換えるにはどこを書き換えればいいですか?

  • 配列の要素数に変数を入れたい

    配列に数の入力履歴を入れて最後にその数を出力したいのですが、変数を入れることはできないと勉強した記憶がありまさにその通りコンパイルエラーが出ました。 他に何か方法はありませんでしょうか。 /* 課題1-3 */ #include <time.h> #include <stdio.h> #include <stdlib.h> #include <math.h> int main(void) { int i; int no1; /* 範囲1 */ int no2; /* 範囲2 */ int max; /* 大きい乱数 */ int min; /* 小さい乱数 */ int y; /* 当てさせる数 */ int stage; /* 入力回数 */ int x; /* 読み込んだ値 */ int n; /* 入力制限 */ srand(time(NULL)); no1 = rand(); no2 = rand(); if(no1 > no2){ max = no1; min = no2; } else{ max = no2; min = no1; } y = min + rand() % (max-min); n = ceil(log(max-min)/log(2)); int a[n]; /*←配列の要素数をn個にしたい*/ printf("%d以上%d以下の整数を当ててください。\n", min, max); stage = 0; do{ printf("残り%d回。いくつでしょう:\n", n - stage); scanf("%d", &x); a[stage++] = x; if(y > x) printf("小さいです。\n"); else if(y < x) printf("大きいです。\n"); }while(y != x && stage < n); if(y != x) printf("残念でした。正解は%dです。", y); else printf("正解です。%d回目で正解しました。", stage); puts("\n---入力履歴---"); for(i=0; i<stage; i++) printf("%2d : %4d %+4d\n", i+1, a[i], a[i] - y); return (0); }

  • C言語の問題です!!

    すみません。 詳細表示をする際に、未ソート部の先頭要素の上に記号文字「*」を表示し、未ソート部の最小要素の上に記号文字「+」を表示したいと思い、以下のソースプログラムを作成したのですが、結果が何か違う気がします…。どこが違うのか、教えていただけませんか? また、プログラムを修正していただけませんか? #include<stdio.h> #include<stdlib.h> #include<time.h> #define swap(type,x,y) do{type t=x;x=y;y=t;}while(0) /*--- 単純選択ソート ---*/ void selection(int a[], int n) { int i, j,k,flg; char *disp[]={" ","[* ]","[ +]","[*+]"}; for (i = 0; i < n - 1; i++) { int min = i; for (j = i + 1; j < n; j++) { if (a[min] > a[j]) { min = j; } } for (k = 0; k < n; k++) { flg=0; if(k==i) flg|=1; if(k==min) flg|=2; printf("%s",disp[flg]); } printf("\n"); for (k = 0; k < n; k++) printf("[%2d]", a[k]); printf("\n"); swap(int, a[i], a[min]); } } int main(void) { int i, nx; int *x; printf("要素数 : "); scanf("%d", &nx); x = calloc(nx, sizeof(int)); srand(time(NULL)); for (i = 0; i < nx; i++) { x[i] = rand() % 100; printf("x[%d] = %d\n", i, x[i]); } selection(x, nx); for (i = 0; i < nx; i++) printf("x[%d] = %d\n", i, x[i]); free(x); return 0; }

  • 引数に二重配列のある関数について

    void calc(int *a,int b,int c){ a[0]=b+c; a[1]=b-c; } void main(void){ int x[2]; int y=2,z=5; calc(x,y,z); printf("x[0]=%d,x[1]=%d\n",x[0],x[1]); } 上のように引数が普通の配列の関数ならできるのですが, 引数が下のような多重配列になるとエラーが出てしまいできません。 void keisan(int **a,int b,int c){ a[0][0]=b+c; a[0][1]=b-c; a[1][0]=b*c; a[1][1]=b/c; } void main(void){ int x[2][2]; keisan(x,6,2); printf("x[0][0]=%d,x[0][1]=%d\n",x[0][0],x[0][1]); printf("x[1][0]=%d,x[1][1]=%d\n",x[1][0],x[1][1]); } 引数に多重配列を使った場合の関数の作り方について教えてください. お願いいたします.

  • callocで二次元配列を作成するには?

    今、動的オブジェクトの勉強をしております。 動的の一次元配列の作り方として #include <stdio.h> #include <stdlib.h> int main(void) {    int *a;    int x;    printf("配列の大きさX入力>");    scanf("%d",&x);    a=calloc(x,sizeof(int));    return (0); } これでいいと思うんですが動的な2次元配列を 作りたいときはどのようにすればよろしいのでしょうか? (↓作りたい二次元配列の例(1)↓) int main(void) {    int *a;    int x , y;    printf("配列の大きさX入力>");    scanf("%d",&x);         //5と入力    printf("配列の大きさY入力>");    scanf("%d",&y);         //10と入力    上のように入力するとa[5][10]という配列が完成する } よろしくお願いします

  • C言語の演算について

    次のプログラムを実行したらどう出力されますか。 微妙な代入演算の違いが分からないので、教えていただけないでしょうか。 #include<stdio.h> void main (void) { int x = 5; int y = 8; int z = 3; int a,b,c,d,e,f; a = y == x + z; b = !x; c = x + y / z; d = x *=z - 1; e = --y / --z; f = y+++ % x++; printf("%d,%d,%d,%d,%d,%d\n",a,b,c,d,e,f); } できれば途中のトレースも書いていただけると助かります。 よろしくお願いします。

  • 参照による呼び出し

    参照による呼び出しで3つの整数を大きい順に並び替えるという プログラムで、 #include<stdio.h> void change(int *x,int *y,int *z);/       main(){ int a,b,c; scanf("%d %d %d",&a,&b,&c); printf("入力データ:a=%d,b=%d,c=%d\n",a,b,c); change(&a,&b,&c); printf("入れ替え後:a=%d,b=%d,c=%d\n",a,b,c); return(0); } void change(int *x,int *y,int *z){ if(*x>*y){ *a=*x; *c=*y; } else{ *a=*y; *c=*x; } if(*z>*a){ *b=*a; *a=*z; } else if(*z>*c){ *b=*z; } else{ *b=*c; *c=*z; } } のように作ったのですが、zの値が一度も使われていないとエラーが 出てしまいます。どこをどう直せばいいか教えてください。 お願いします。

  • 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 】はどうすれば出来ますか教えてください。お願いします。

専門家に質問してみよう