• 締切済み

ヒープ deleteminの関数作成がわかりません

問題文:ヒープの最小値を取り除く、deletemin関数を作成せよ。空の配列にinsertを複数実行することでヒープ条件を満たすヒープを構成する。これにdeleteminを実行することで最小値を抽出せよ。最小値を抽出した後、一次元配列がヒープ条件を満たすように再構成せねばならない。プロトタイプ宣言は以下とする。 int deletemin(int a[], int *n); 質問:関数deleteminについて調べてはみたんですが何をしているのか分からないものばかりだったので質問させてください。ヒープの最後のノードを根に持ってきて、右のノードと左のノードを比べて小さい値のノードの方と比較して最後から持ってきたノードの値の方が大きければ交換するというの繰り返して最小ヒープを再構成したいのですが、どうすればいいのかわかりません。サイトなどみても分からなかったのでど素人でも分かるように説明お願いします。 以下自分のソース #include<stdio.h> #include<stdlib.h> #include<time.h> int check_heap(int a[], int n); void insert(int val, int a[], int *n); int deletemin(int a[],int *n); int main(void) { int a[12] = {1,13,71,14,15,80,91,24,60,63}; int n; int i; int b,c; srandom(time(NULL)); b = random() % 100 + 1; n = 10; insert(b, a, &n); n = 11; c = random() % 100 + 1; insert(c, a, &n); printf("%d\n", check_heap(a, 12)); deletemin(a, &n); return 0; } int check_heap(int a[], int n) { int i; int m; m = (n - 1) / 2; for(i = 0; i < m; i++) { if(a[i] >= a[i * 2 + 1]) { return 0; } if(a[i] >= a[i * 2 + 2]){ return 0; } } if(n % 2 == 0){ if(a[(n - 1)/2] > a[n - 1]){ return 0; } } return 1; } void insert(int val, int a[], int *n) { int temp; int i; a[*n] = val; i = *n; while( 0 < i){ if(a[(i-1)/2] <= a[i]) { break; } temp = a[(i-1) / 2]; a[(i-1) / 2] = a[i]; a[i] = temp; i = (i - 1)/2; } } int deletemin(int a[],int *n){ int b; int i,j,k; b = a[0]; return b; }

みんなの回答

  • jjon-com
  • ベストアンサー率61% (1599/2592)
回答No.2
全文を見る
すると、全ての回答が全文表示されます。
回答No.1

URL参照。

参考URL:
http://codezine.jp/article/detail/3864
全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 一次元配列で表現された最小ヒープの値挿入

    問題文:ヒープに新たなデータを挿入する関数insertを作成せよ。空の配列に複数回insertを行うことで 構成したヒープがヒープ条件を満たしていることをcheck_heapを用いることで確認せよ。プロトタイプ宣言は以下とする。 void insert(int val, int a[],int *n); 質問:  複数回はおいといてとりあえず1回insertしようと思って書いたんですが、ヒープの最後に新しいノードを 作って親より小さければ親の値と交換を繰り返してヒープを完成させようとしてるんですが、1回しか交換されません。 どうすればいいですか?check_heapは最小ヒープ条件が満たされていれば1を満たされていなければ0を返す関数です。 自分のソース #include<stdio.h> #include<stdlib.h> #include<time.h> int check_heap(int a[], int n); void insert(int val, int a[], int *n); int main(void) { int a[11] = {1,13,71,14,15,80,91,24,60,63}; int n; int i; int b,c; srandom(time(NULL)); b = random() % 100 + 1; n = 10; insert(b, a, &n); printf("%d\n", check_heap(a, 11)); for(i = 0; i < 11; i++){ printf("%3d", a[i]); } return 0; } int check_heap(int a[], int n) { int i; int m; m = (n - 1) / 2; for(i = 0; i < m; i++) { if(a[i] >= a[i * 2 + 1]) { return 0; } if(a[i] >= a[i * 2 + 2]){ return 0; } } if(n % 2 == 0){ if(a[(n - 1)/2] > a[n - 1]){ return 0; } } return 1; } void insert(int val, int a[], int *n) { int temp; a[*n] = val; while(a[(*n-1) / 2] >= a[*n]){ temp = a[(*n-1) / 2]; a[(*n-1) / 2] = a[*n]; a[*n] = temp; } }

  • ヒープの探索の再帰

    A[N]を利用したヒープのプログラムを作りました。 A[i]の親は、A[(i-1)/2]であるヒープです。 (上に行くほど小さい整数を格納) そしていまある整列されたヒープのなかからキーボードから入力した値xを検索する関数findを、 x ←検索する値 A[]←ヒープソートされた配列 n ←格納されているA[]の最後の添え字 として、 int find(int x, int *A, int i, int n) { if(A[i]==x){ printf("*\n"); /* ここの作業が行われているかを確認 */ return 1; } if(i>n)return 0; if(A[i]>x){ return 0; } else if (A[i]<x){ i = 2*i + 1; find(x, A, i, n); i++; find(x, A, i, n); } return 0; } というものを作ってみました。汚いかもしれませんが、とりあえず今はこれでいっぱいいっぱいです。 それで、当然のごとくうまくいきませんでした。 /**/内に書いたように、入力したxがヒープ内にある場合は「*」が一応表示されるのですが、どうもfindは1を返してくれません。0を返してしまいます。見つけた後もまだ再帰をくりかえしえしているようです。 どこがいけないのでしょうか。

  • ヒープの探索の再帰 改め

    前回の質問は↓ http://oshiete1.goo.ne.jp/kotaeru.php3?q=658496 です。 前回の質問は何とか自己解決できました。 int find(int x, int *A, int i, int n) { if(A[i] == x)return 1; if(i>n)return 0; if(A[i]>x)return 0; if(A[i]<x){ i = i*2 + 1; if(find(x, A, i, n))return 1; i++; if(find(x, A, i, n))return 1; } return 0; } そして関数呼び出しの際に、 find(x, A, 0, n); とすることにより、探索が可能になりました。ただやはりもっと簡単にできそうな気がするのですが、思いつきません。もっと綺麗に書けるのならその書き方を教えて欲しいです。

  • 最小ヒープソートについて

    問題:numbers.datから10個の整数を読みこみヒープソートで昇順に表示せよ。 numbers.dat 91 63 71 14 60 1 24 13 80 15 質問:下記が自分のコードなんですが実行すると 1 13 13 13 13 13 13 13 13 13になるんですが、何を直せばいいでしょうか。最小の値を取り出していくようにしているつもりなんですが #include<stdio.h> #include<stdlib.h> void insert( int i,int a[], int n); int deletemin(int a[], int n,int m); int main() { int a[10],m[10]; int i,j,k; int n = 10; FILE *fp; fp = fopen("numbers.dat", "r"); if(fp == NULL) { printf("ファイルが開けません\n"); return 1; } fscanf(fp,"%d %d %d %d %d %d %d %d %d %d\n",&a[0] ,&a[1] ,&a[2] ,&a[3] ,&a[4] ,&a[5] ,&a[6] ,&a[7] ,&a[8],&a[9] ); for(i = (n - 2)/2; i >= 0; i--) { insert(i, a, n-1); } for(i = n-1; i >= 0; i-- ) { m[9-i] = deletemin(a, i, n-1); } for(j = 0; j < 10; j++){ printf("%3d",m[j]); } return 0; } void insert( int i,int a[], int n) { int j; int temp; while (2 * i + 1 <= n) { j = 2 * i + 1; if (j < n) { if (a[j] > a[j + 1]) { j++; } } if (a[i] <= a[j]) { break; } temp = a[j]; a[j] = a[i]; a[i] = temp; i = j; } } int deletemin(int a[],int n, int m) { int b; int temp; int i,j; b = a[0]; a[0] = a[n]; i = 0; while (2 * i + 1 <= m) { j = 2 * i + 1; if (j < m) { if (a[j] > a[j + 1]) { j++; } } if (a[i] <= a[j]) { break; } temp = a[j]; a[i] = a[j]; a[i] = temp; i = j; } return b; }

  • 配列にデータを10個読み込み、最大のものと、最小のものの差を求めるプログラム

    #include <stdio.h> int main(){ double a,b[10]; int c,i; a=0; for(i=0;i<=10;i++) { scanf("%lf", &b[i] ); }if ( b[i] > a ){ b= a; }return 0;} 最大値と最小値を求めるのに、b=aを繰り返すにはどう書いたらいいですか?

  • Random#nextInt(int n)の実装

    Java 2 (1.4) のドキュメントによれば、java.util.Random#nextInt(int n) の実装は public int nextInt(int n) { if (n<=0) throw new IllegalArgumentException("n must be positive"); if ((n & -n) == n) // i.e., n is a power of 2 return (int)((n * (long)next(31)) >> 31); int bits, val; do { bits = next(31); val = bits % n; } while(bits - val + (n-1) < 0); return val; } となっているようですが、  return (int) (getDouble() * n) ; // もっとも簡単な実装 ではないのは何故ですか。精度上の問題があるのでしょうか?

  • c言語の再帰で(関数呼び出し)+1がわからない

    再帰がどのように処理されているのか理解するために、再帰の時に +1 してみたところ 0! = 1 1! = 2 2! = 5 3! = 16 4! = 65 5! = 326 6! = 1957 7! = 13700 8! = 109601 9! = 986410 10! = 9864101 となりました。 普通の階乗の値を求めた最後に +1され、それが戻されると思ったのですが違いました。 これはどういう処理がされているのでしょうか? #include <stdio.h> int kaijo(int); int main() { int i; for (i = 0; i < 11; i++) printf("%d! = %d\n", i, kaijo(i)); return 0; } int kaijo(int n) { if (n == 0) return 1; else return n * kaijo(n - 1) + 1; }

  • C言語 ソートについて

    #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { } bool is_at(char c) { } void justify(char line[], int n) { } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; } 上の雛形を使って文字列lineに含まれる@以外の文字を文字列の前の方に詰めていくプログラミングを作るという問題を解いていたのですが下のプログラミングまでは出来たのですが最後のjustifyの部分がわかりません 良ければ解答をお願いします #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { char temp = *a; *a = *b; *b = temp; } bool is_at(char c) { if(c == '@') { return true; } else { return false; } } void justify(char line[], int n) { for(int i=0;i<n-1;i++) { } } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; }

  • 関数のパラメータを配列に格納したいのですが

    #include<stdio.h> #include<stdlib.h> int func(int, int, int, int); int main(void) { int a = 3, b = 4, c = 5, d = 6; int sum; sum = func(a, b, c, d); printf("合計は%dです。\n", sum); return EXIT_SUCCESS; } int func(int m, int n, int o, int p) { int Hairetu[4]; int Sum = 0; int i; /* ここで、Hairetuにm, n, o, pを格納したい */ for(i=0; i<4; i++) Sum += Hairetu[i]; return Sum; } 例えばこのようなプログラムがあった時、m, n, o, pの値をHairetuに格納するには、どのようにすればよいのでしょうか。 分かりにくい文章ですが、どうかよろしくお願い致します。

  • 関数におけるif文とreturn文について

    ◎1-------------------------------------------- #include<stdio.h> #include<math.h> double maxdt(double a,double b); void disp_sqrt(double n); int main(void) { double mx; mx=maxdt(22.33,44.55); printf("mx=%f\n",mx); disp_sqrt(3.0); disp_sqrt(-6.0); return 0; } double maxdt(double a,double b) { if(a>b) return a; else return b; } void disp_sqrt(double n) { if(n<=0.0) return; printf("%f の平方根=%f\n",n,sqrt(n)); } ----------------------------------------------- ◎2------------------------------------------- #include<stdio.h> #include<math.h> double maxdt(double a,double b); void disp_sqrt(double n); int main(void) { double mx; mx=maxdt(22.33,44.55); printf("mx=%f\n",mx); disp_sqrt(3.0); disp_sqrt(-6.0); return 0; } double maxdt(double a,double b) { if(a>b) return a; else return b; } void disp_sqrt(double n) { if(n<=0.0){ return; printf("%f の平方根=%f\n",n,sqrt(n)); } } ----------------------------------------------- ◎3-------------------------------------------- #include<stdio.h> #include<math.h> double maxdt(double a,double b); void disp_sqrt(double n); int main(void) { double mx; mx=maxdt(22.33,44.55); printf("mx=%f\n",mx); disp_sqrt(3.0); disp_sqrt(-6.0); return 0; } double maxdt(double a,double b) { if(a>b) return a; else return b; } void disp_sqrt(double n) { if(n<=0.0){ return; } else{ printf("%f の平方根=%f\n",n,sqrt(n)); } } -------------------------------------------------- ◎1は参考書を参考に作ったものです。 ◎1は正常に動きます。 以上3つのプログラムで、疑問に思ったのは、関数「void disp_sqrt(double n);」についてなのですが、自分はif文が文が1つでもカッコ{ }を付けたい考えなので、◎1の「void disp_sqrt(double n)」の関数のif文に{}を付けようと思い、まず◎2のように変えたところ、平方根の表示が何も出ませんでした。 return文も文の1つだと考え、◎3のような形は正常に動きました。 return文とprintf文の2つの文があるという考えは間違っているのでしょうか? 後、◎1は何故{ }が無くてもよく、◎2は何も表示されないのでしょうか? 教えていただけると嬉しいです。

このQ&Aのポイント
  • MFC-J6583CDWでexcelの2in1印刷ができないというお困りの方へ解決方法をご紹介します。
  • Windows11をお使いの方で、MFC-J6583CDWでexcelの2in1印刷ができない場合の対処法をご紹介します。
  • MFC-J6583CDWを無線LANで接続している方で、excelの2in1印刷ができない場合のトラブルシューティング方法をご紹介します。
回答を見る