• 締切済み

heapsortについて問題

以下の問題はある国立大学の大学院入試過去問題です 空欄を埋めて、プログラムを完成させなさい。 よろしくお願い致します 以下はheapを建てるための方法 void in(int dt,int*val) { int i; val[0]++; for(i=val[0];i>1&&dt<val[i/2];i=i/2) val[i]=val[i/2]; val[i]=dt; } 以下はsort方法だ int dl(int *val){ int i=1,j,ret= 空欄 ;←自分の考えはval[i]です while(i<=val[0]/2){ j=2*i; if(j+1<val[0]&& 空欄 < 空欄 )←自分の考えはval[j+1]<val[j] j++; if(val[val[0]]<val[j]) break; val[i]=val[j]; i=j; } val[i]=空欄;←自分の考えはval[i]=nullです、でも納得できない val[0]--; return ret; } void hs(int sz,int d[]) { int i,*val; val = malloc(sizeof(int)*(sz+1)); val[0]=0; for(i=0;i<sz;i++) in(d[i],val); for(i=0;i<sz;i++) d[i]=dl(val); } orzorzorzorzorz

みんなの回答

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.3

> あ。。。分かった、 > この空欄がval[val[0]]だ。 > でもこういうheapsortは確かに分かりにくいです 正解。 おめでとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • Yanch
  • ベストアンサー率50% (114/225)
回答No.2

トレースでどこまでわかっていますか? わかっている事実を書いてくれるとアドバイスを貰いやすいかもしれません。 > szが{2,0,3,1}だったとすると、 この一文は、意味不明ですが、タイプミスであると想像してみます。 hs(sz, d) 関数を呼び出すのにしようするデータが、 sz に 4、d に {2,0,3,1}と言う事だろうと思って読んでみます。 > 建てされたheapは > val[0]=4, > val[1]=0; > val[2]=1, > val[3]=3, > val[4]=2 > です > そうすると、0,1を脱出した後は、 この0, 1を脱出した後って、言うのは、valの添え字の事ですか?それとも、内容の事ですか? 手前でのトレース情報一部を書いてみます。 hs(sz, d)に、sz に 4 を, d に {2,0,3,1} を指定した場合、 建てられた heap 、 val は{4, 0, 1, 3, 2}ですね。 そして、 dl(val)を脱出するごとに、 val は {3, 1, 2, 3} val は {2, 2, 3} val は {1, 3} val は {0} となってます。

firemanryu
質問者

お礼

あ。。。分かった、俺が馬鹿になったぞ。。 この空欄がval[val[0]]だ。 でもこういうheapsortは確かに分かりにくいです

firemanryu
質問者

補足

また対応して有難うございます。 脱出順番はもちろん以下です val は {3, 1, 2, 3} val は {2, 2, 3} val は {1, 3} val は {0} しかし、val[i]=空欄、 空欄っていうところに何を埋めたほうがいいか是非教えていただきたいです

全文を見る
すると、全ての回答が全文表示されます。
  • Yanch
  • ベストアンサー率50% (114/225)
回答No.1

ヒープソートのコーディングは、もっとわかりやすい書き方があると思いますが、 これは穴埋めが目的の課題みたいなので、わざとわかりにくくしているのでしょう。 > int i=1,j,ret= 空欄 ;←自分の考えはval[i]です これは、正解。 int i=1,j,ret= val[1] ;でも良いと思います。 > if(j+1<val[0]&& 空欄 < 空欄 )←自分の考えはval[j+1]<val[j] これは、正解。 > val[i]=空欄;←自分の考えはval[i]=nullです、でも納得できない これは、間違い。 データのトレースをすれば、なにを書くべきかあきらかになると思いますよ。

firemanryu
質問者

補足

早速ご対応ありがとうございます、 でも何度も繰り返しトレースをしてみると、 何を書くべきかわからないです、 何卒教えてください。 ちなみに俺の迷いところは以下です szが{2,0,3,1}だったとすると、 建てされたheapは val[0]=4, val[1]=0; val[2]=1, val[3]=3, val[4]=2 です そうすると、0,1を脱出した後は、 残り分はval[1]=2;val[3]=3, こうなると、どうすればいいですか

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 基本選択法

    宜しくお願いします。 基本選択法のプログラムを書いていますが、コンパイルは通りますが、うまくソートされません。 改良点をご教示ください。 #課題ではありません。 #include <stdio.h> int getMin(int in[], int n, int a); void swap(int *m, int *n); int main(void) {   int a[10] = { 84, 121, 43, 93, 140, 83, 14, 93, 181, 58};   int i, j, k;   for(i=0; i<10; i++){     k = getMin(a, 10, i);     swap(&a[i], &a[k]);     for(j=0; j<10; j++){       printf("a[%d] = %d ", j, a[j]);     }     printf("\n");   }   return 0; } void swap(int *m, int *n) {   int tmp;   tmp = *m;   *m = *n;   *n = tmp; } int getMin(int in[], int n, int a) {   int i, ret, min;   min = in[a];   ret = 0;   for(i = a; i < n; i++)   {     if(in[i] < min){       min = in[i];       ret = i;     }   }   return ret; }

  • C言語の配列の入れ方について質問です。

    下記のプログラムで1234という連続した数字を入れたら配列val[0]~[3]に val[0] = 1 val[1] = 2 val[2] = 3 val[3] = 4 というように入れたいのですが、どのようにして別々にすれば良いですか?宜しくお願いします。 #include<stdio.h> int main(void) { int num[10]; int val[4]; int i; printf("式:"); scanf("%d",num); for(i=0;i<4;i++){ val[i] = 0; } for(i=0; i<4; i++){ if((num[i] >= 1) && (num[i] <= 9)){ /*1から9の数値が入ったならば*/ val[i] = num[i]; } } for(i=0; i<4; i++){ printf("答え%d:%d\n",i,val[i]); } }

  • シェルピンスキーのギャスケット

    基本情報技術者試験のH15、春期 問6の問題を実際に組んでみても なぜか問題のように動いてくれません。 どこが間違っているのでしょうか? 環境は Borland になります。 #include<stdio.h> #define ALIVE 1 #define DEAD 0 #define SZ 33 int stschk(int ,int); int main(void) { int s[SZ][SZ],i,j; for(i=0; i<SZ; i++) s[i][0] = DEAD; for(j=2; j<SZ; j++) s[0][j] = DEAD; s[0][1] = ALIVE; for(i=0; j<SZ-1; i++){ for(j=1; j<SZ; j++){ s[i+1][j] = stschk(s[i][j], s[i][j-1]); if(s[i][j] == ALIVE) printf("*"); else printf(" "); } printf("\n"); } return 0; } int stschk(int s1, int s2) { if(((s1 == DEAD)&&(s2 == ALIVE)) || ((s1 == ALIVE)&&(s2 == DEAD))) return ALIVE; else return DEAD; } よろしくお願いします。

  • C言語のプログラミングについて質問です。

    以下の文を出力して入力:に16進数を入れると10進数に変換した数値の小さい列順に並ぶプログラムを作りたいのですがうまく出来ません。 仕様は以下に記載します。 入力:__、__、__、__、__EnterKeyで結果を表示。 以下のバブルソートの文のどこをいじれば良いでしょうか? 返答宜しくお願いします。 #include <stdio.h> int main (void) { char data[256]; int val[100]; int i = 0; int work; int j; int k; printf("入力 = "); scanf("%s",data); for(i=0;i<100;i++){ val[i] = 0; } k=0; for(i = 0;i<100 ; i++){ if(data[i] == 0x00){ //data[i]がNULLだったら処理を抜ける k++; break; //enterキーでprintf出力 } else if(data[i] == ','){ //カンマだったら /*printf("%d\n",k);*/ k++; } else{ if(data[i] >= 'A' && data[i] <= 'Z'){ //data[i]にAからZが入ったら val[k] = val[k] *16 + data[i] -'A'+10; } else if(data[i] >= '0' && data[i] <= '9'){ //data[i]に0から9が入ったら val[k] = val[k] *16 + data[i] -'0'; } } } /* printf("k=%d\n",k); for(i=0;i<k;i++){ printf("出力 = %d\n",val[i]); } */ //バブルソート//     for(i=0; i<k-1; i++) { if(val[i] < val[i+1]) { } else{ work = val[i]; val[i] = val[i+1]; val[i+1] = work; } } for(i=0;i<k;i++) { printf("出力 = %d\n",val[i]); } }

  • C言語の問題で一部分からないところがあります。

    C言語の問題で2つの4x4行列の2次元配列に格納し、それらの積を求めるというプログラムで以下のような関数を作成しました。 #include <stdio.h> void m_ena(int a0[4][4], int a1[4][4], int result[4][4]); int main(void) { } void m_ena(int a0[4][4], int a1[4][4], int result[4][4]) { int a[4][4], b[4][4], r[4][4]; int i, j; for(i=0; i<4; i++){ for(j=0; j<4; j++){ scanf("%d", &a[i][j]); } } for(i=0; i<4; i++){ for(j=0; j<4; j++){ scanf("%d", &b[i][j]); } } for(i=0; i<4; i++){ for(j=0; j<4; j++){ r[4][4] = a[i][j]*b[i][j]; } } } ここまで出来たのはいいのですが、これ以降どのようにメイン関数に書けばいいのか分からず困っています。 この問題は必ず上記関数を使う必要がありますのでどうぞよろしくお願いします。

  • クイックソートのアルゴリズムが分かりません><;

    C言語初心者の学習を終えて、アルゴリズムの構造を学んでいる段階のものです。バブルソートを実装することは成功したのですが、クイックソートが実装できません>< 以下は文字列をバブルソートできるアルゴリズムです。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define MAXCHARSINONELINE 400 #define LINETABLESIZE 100 char linetable[LINETABLESIZE][MAXCHARSINONELINE]; int resultindex[LINETABLESIZE]; int maxtableindex = 0; void addToTable(char *); void initresult(); void mysort(); int mycompare(int, int); void myswap(int, int); char mark[2]; int start; int end; int main(void) { char line[MAXCHARSINONELINE]; char *ret; int i; do { ret = fgets(line,MAXCHARSINONELINE,stdin); if( ret != NULL ) { addToTable(line); } } while(ret != NULL); fprintf(stderr,"sorting...\n"); start = clock(); /* for(i=0; i<10000; i++){ */ initresult(); mysort(); /* } */ end = clock(); fprintf(stderr,"[%f sec]\n",(float)(end-start)/CLOCKS_PER_SEC); fprintf(stderr,"[results]\n"); for( i = 0; i < maxtableindex; i++ ) { printf("(L.%3d):%s",resultindex[i]+1, linetable[ resultindex[i] ]); } return 0; } void addToTable(char *data) { if( maxtableindex >= LINETABLESIZE ) { fprintf(stderr,"Table is full.!\n"); exit(0); } strncpy( linetable[maxtableindex], data, MAXCHARSINONELINE ); maxtableindex++; } void initresult() { int i; for( i = 0; i < maxtableindex; i++ ) { resultindex[i] = i; } } void mysort() { int i,j,k; for( i = maxtableindex-1; i > 0; i-- ) { for( j = 0; j < i; j++ ) { /* printf("--\n"); for(k = 0; k < maxtableindex; k++) { if((k == j) || (k == j + 1)) { strcpy(mark,"*"); } else { strcpy(mark," "); } printf("%s %s", mark, linetable[resultindex[k]]); } printf("--\n"); */ if( mycompare(j, j + 1) > 0) { /* printf("swap %d <----> %d\n",j ,j + 1); */ myswap(j, j + 1); } } } } int mycompare(int i, int j) { return strcmp(linetable[resultindex[i]], linetable[resultindex[j]]); } void myswap(int i, int j) { int tmp; tmp = resultindex[j]; resultindex[j] = resultindex[i]; resultindex[i] = tmp; } このプログラムを改編して、クイックソートにしたいのですが、どこをどうすればよいのでしょうか。 長くなってすみません。 ご回答をお願いします。

  • 消滅したローカル変数のメモリ領域への上書きについて

    Cプログラミング初心者のものです。 課題でわからないところがあるので質問いたします。 以下ソース typedef struct comp{ int val1; int val2; }*comp_t,comp_val; comp_t first(); void second(); int main(int argc, char **argv){ comp_t ret; ret=first(val); second(); printf("Val1=%d,Val2=%d\n",ret->val1,ret->val2); } comp_t first(){ comp_val comp; comp.val1=10; comp.val2=20; return &comp; } void second(){ int a=-100; int b =-200; } 実行すると Val1=-200,Val2=-100 と出ます。ローカル変数が消滅し、second()で新たなintを二つ定義しているので、キレイに上書きされて結果が出たことはわかるのですが、 それなら普通、-100,-200の順に出るのではないのでしょうか。 なぜ裏返ってしまったのでしょう? また、それはソースを見ただけでわかるものなのでしょうか。 返信お願いします。

  • 巡回セールスマン問題

    巡回セールスマン問題の解を求めるプログラムを作ったのですが、これでは全ての回路が表示されてしまいます。最小値だけでしかも順列の最初の値が0の回路だけを表示させるにはどうすればいいのでしょうか?どなたか教えてください。長くてすいません。 #include<stdio.h> #define MAXN (100) #define YES (1) #define NO (0) void perm(int d); int n, a[MAXN], used[MAXN]; int dist[MAXN][MAXN]; int main(void) { int i; int j; // printf("Input n: "); scanf("%d", &n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { scanf("%d", &dist[i][j]); } } if (n > MAXN) { printf("Change the value MAXN.\n"); exit(1); } else if (n < 0) { printf("Error!(Input nonnegative integer.)\n"); exit(1); } for (i = 0; i < n; i++) used[i] = NO; /* 始めはどの値も使っていない */ perm(0); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { printf("%2d ", dist[i][j]); } printf("\n"); } } /* 深さdの節点を根とする木を作成する関数 */ void perm(int d) { int i; if (d == n) { for(i = 0; i < n; i++) printf("%d", a[i]); printf("\n"); } else { for (i = 0; i < n; i++) { if (used[i] == NO) { a[d] = i; /* 配列のd番目にiを代入する */ used[i] = YES; /* iを使ったことを記憶する */ perm(d + 1); /* 再帰呼び出し */ used[i] = NO; /* 命令文を追加する */ } } } }

  • 先頭0で重複のない配列を作りたい

    重複なく4つの領域を持つ配列に数字を代入したい(先頭は0以外の 数字)と思って書いたプログラムです。 しかし、コンパイルしてみると重複が発生してしまいます。 これはなぜ発生してしまうのでしょうか? よろしくお願いします。 #include<stdio.h> #include<stdlib.h> #include<time.h> int main(void) { int num,val,i,j; int comp[4]; srand(time(NULL)); puts("4桁の数字を記憶して逆向きに入力しましょう。"); val=rand()%10; do{ comp[0]=val; }while(comp[0]==0); for(i=1;i<4;i++) { do{ val=rand()%10; for(j=0;j<i;j++) { if(comp[j]==val) { break; } } }while(i<j); comp[i]=val; } for(i=0;i<4;i++) { printf("%d",comp[i]); } return 0; }

  • ヒープソートを教えてください

    本を読んで作ってみたのですが、ソートしてくれません。。 void down(int from, int to); void heapsort(char s[][WC],int n); void down(int from, int to){ int i=1, j; char s[NS][WC],val; val = s[from][WC]; i = from; while(i <= to/2){ j = i*2; if(j+1 <= to && strcmp(s[j],s[j+1])>0) j++; if(strcmp(s[j],s[from])>0) break; strcpy(s[i],s[j]); i = j; } s[i][WC] = val; } void heapsort(char s[][WC],int n) { int i; char tmp[WC]; for(i = n/2; i >= 1; i--) down(i, n); for(i = n; i >=2; i--){ strcpy(tmp,s[1]); strcpy(s[1],s[i]); strcpy(s[i],tmp); down(1, i-1); } }

このQ&Aのポイント
  • ラベル印刷時にずれが発生し、うまくいかないという問題があります。Windows10のパソコンに有線LANで接続しており、光回線を使用しています。解決策を教えてください。
  • ブラザー製品のMFC-2750DWでラベル印刷を行う際に、印刷がずれてしまう問題が発生しています。接続はWindows10のパソコンに有線LANで行っており、光回線を使用しています。問題の解決策を教えてください。
  • MFC-2750DWのラベル印刷時にずれが発生し、うまく印刷ができません。接続環境はWindows10のパソコンに有線LANで、光回線を使用しています。この問題の解決策を教えてください。
回答を見る

専門家に質問してみよう