• ベストアンサー

make_heap()が分かりません

#include <iostream> #include <vector> #include <algotithm> using namespace std; int main() { vector<char> v; int i; for(i=0;i<20;i+=2)v.push_back('A'+i); couti<<"sequence before building heap:\n"; for(i=0;i<v.size();i++)cout<<v[i]<<" "; cout<<"\n\n"; make_heap(v.begin(),v.end()); //? couti<<"sequence after building heap:\n"; for(i=0;i<v.size();i++)cout<<v[i]<<" "; cout<<"\n\n"; } の結果が sequence before building heap: A C E G I K M O Q S sequence after building heap: S Q M O I K E A G C ということですが make_heap() の機能がわかりません make_heap() の機能・動作に付いて教えてください (書き間違いがあるかもしれませんので容赦ください)

  • nubou
  • お礼率62% (293/470)

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

  • ベストアンサー
回答No.6

> 0,2,4,6,8,10,12,14,16,18のヒープと > 0,2,4,6,8,10,14,12,16,18のヒープは違うのですね? > つまり初期条件によってヒープ結果は違ってくるのですね? そういうことになりますかねぇ。

nubou
質問者

お礼

#include <iostream> #include <vector> #include <algorithm> using namespace std; void main() {  vector<int> v;  int i;  for(i=0;i<10;i++)v.push_back(i);  cout<<"heap(";for(i=0;i<(int)v.size();i++)cout<<v[i]<<" "; cout<<")=";  make_heap(v.begin(),v.end()); //?  for(i=0;i<(int)v.size();i++)cout<<v[i]<<" ";  v[0]=0;v[1]=1;v[2]=2;v[3]=3;v[4]=4;v[5]=5;v[6]=7;v[7]=6;v[8]=8;v[9]=9;  cout<<"heap(";for(i=0;i<(int)v.size();i++)cout<<v[i]<<" ";cout<<")=";  make_heap(v.begin(),v.end()); //?  for(i=0;i<(int)v.size();i++)cout<<v[i]<<" "; } をBorland無償コンパイラでコンパイル実行すると heap(0 1 2 3 4 5 6 7 8 9 )=9 8 6 7 4 5 2 0 3 1 heap(0 1 2 3 4 5 7 6 8 9 )=9 8 7 6 4 5 2 0 3 1 となりますから多分そうでしょう heapの意味がなんとなくわかってきました ありがとうございました

その他の回答 (5)

回答No.5

> No.1 にある SGI のドキュメントの Notes を読んでもらった方が良い。 > 英語が厳しいのなら、参考URL の microsoft のページの概説でも。 正しい説明は IS(International Standard:国際規格書) を読むのが一番でしょう。なんせ神様ですから。それによると、 - 先頭要素が一番でかい - 先頭要素の削除および要素の追加にはO(logN)の時間計算量を要する と'だけ'定義されており、その要件さえ満たせばシーケンス内での並びは実装依存ということになります。が、上記用件を満たすとなると必然的にNo.2のような構造にならざるを得ないはずです。 # 宣伝御免 # C++のディープな話題はcppll-ML(下記URL)へ。

参考URL:
http://www.freeml.com/ctrl/html/MLInfoForm/cppll@freeml.com
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.4

あかん、思い切り突っ込まれてる (^^; No.1 の回答は無視して。 どうしたらああいう説明になるんでしょうね。 No.1 にある SGI のドキュメントの Notes を読んでもらった方が良い。 英語が厳しいのなら、参考URL の microsoft のページの概説でも。 # いや、面目ない

参考URL:
http://www.microsoft.com/japan/developer/library/vclang/sample_heap_(STL_Sample).htm#_sample_stl_heap
回答No.3

> SGI のドキュメントを見る限りでは、iterator が container が random access に適した > ものかどうか分からない (iterator が抽象化している) ので、sort をやりやすくするように、 > randam access に適した形にする、という意味があります。 SGIのドキュメントからは、このような解釈は導き出せないのですが...

回答No.2

v[1], v[2], ..... v[N] において、 v[i] >= v[2*i] かつ v[i] >= v[2*i+1] を満足するよう並べ替えられます。 したがって先頭要素が最大となります。 上記の条件を満たすシーケンス(要素の並び)を heapといいます。先頭要素を取り除き、 末尾要素を先頭に置き、また上の条件を満たす ように並び替える...を繰り返すことによって、 シーケンスをソートすることができます。 それがheap_sortです。 > vector は、もともと randam access しやすい > container なので、質問にあるソースだと... というわけで、この説明には疑問が残ります。

nubou
質問者

補足

0,2,4,6,8,10,12,14,16,18のヒープと 0,2,4,6,8,10,14,12,16,18のヒープは違うのですね? つまり初期条件によってヒープ結果は違ってくるのですね? よろしくお願いします

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

SGI のドキュメントを見る限りでは、iterator が container が random access に適した ものかどうか分からない (iterator が抽象化している) ので、sort をやりやすくするように、 randam access に適した形にする、という意味があります。 vector は、もともと randam access しやすい container なので、質問にあるソースだと、 その効果は認められませんが、list や tree のような container を make_heap する 前と後で sort してみると、その効果が出ます。 # と、思います (^^;

参考URL:
http://www.sgi.com/tech/stl/make_heap.html
nubou
質問者

補足

やっぱり書き間違いがあったので訂正します ついでに分かりやすく数字にしました #include <vector> #include <algorithm> using namespace std; int main() { vector<int> v; int i; for(i=0;i<10;i++)v.push_back(i); cout<<"sequence before building heap:\n"; for(i=0;i<(int)v.size();i++)cout<<v[i]<<" "; cout<<"\n\n"; make_heap(v.begin(),v.end()); //? cout<<"sequence after building heap:\n"; for(i=0;i<(int)v.size();i++)cout<<v[i]<<" "; cout<<"\n\n"; return 0; } 結果は sequence before building heap: 0 1 2 3 4 5 6 7 8 9 sequence after building heap: 9 8 6 7 4 5 2 0 3 1 です どうしてこのような並びになるかmake_heapの機能とともに解説していただければ幸いです

関連するQ&A

  • C++で分からないプログラムがあるんですが

    #include <iostream> #include <cmath> using namespace std; int main() { static const int N = 2; double va[N]={3,-4}; double vb[N]={4,3}; double a,b; double p; for (int i = 0; i < N; ++i) { for (int i = 0; i < N; ++i) { } } cout << "va + vb = (" ; for (int i = 0; i < N; ++i) { cout << va[i] + vb[i]; if (i < N - 1) { cout << ", "; } } cout << ")" << '\n'; cout << "va - vb = (" ; for (int i = 0; i < N; ++i) { cout << va[i] - vb[i]; if (i < N - 1) { cout << ", "; } } cout << ")" << '\n'; p = 0; for (int i = 0; i < N; ++i) { p += va[i] * vb[i]; } cout << "va・vb = " << p << '\n'; a = 0; for (int i = 0; i < N; ++i) { a += va[i] * va[i]; } a = sqrt(a); b = 0; for (int i = 0; i < N; ++i) { b += vb[i] * vb[i]; } b = sqrt(b); if (a * b != 0) { cout << "cosθ = " << p / (a * b) << '\n'; } return 0; } これで、ベクトルの加減とベクトルの内積とcosθが出るんですが、2つのベクトルを適当に初期化しないといけないんですが、初期化ってこれで初期化ってできてますか?

  • CygwinでSTLの勉強をしていますが・・・

    今C++のSTLの勉強をしています。 本に載っているサンプルプログラムを打って実行しようとしたら エラーがでてしまいました。 エラーの内容はprintとtotalが見つかりませんというエラーです。 コンパイラはcygwinを使ってます。 よろしくお願いします。 /*for_each()アルゴリズム*/ #include<iostream> #include<algorithm> #include<vector> #include<functional> #include<> using namespace std; int main() { int n[]={100,200,300,400,500,600}; int size=sizeof n/sizeof(int),i; vector<int> v; for(i=0;i<size;++i) v.push_back(n[i]); for_each(v.begin(),v.end(),print<int>()); cout<<endl; cout<<(for_each(v.begin(),v.end(),total<int>())).gettotal()<<endl; return 0; }

  • 単純挿入法を入れたいんですけど・・・

    #include <iostream> #include <iomanip> #include <cstdlib> //rand関数を使うので using namespace std; void Sort(int *s, int n); //プロトタイプ int main() { const int N = 100; int a[N], i, r, temp; for(i = 0; i < N; i++) a[i] = i; for(i = 0; i < N; i++){ r = rand() % N; temp = a[i]; a[i] = a[r]; a[r] = temp; } cout << "整列前\n----\n"; for(i = 0; i < N; i++) cout << setw(4) << a[i]; cout << '\n'; Sort(a, N); cout << "整列後\n----\n"; for(i = 0; i < N; i++) cout << setw(4) << a[i]; cout << '\n'; return 0; } void Sort(int *s, int n) { //この部分を補って完成させること }

  • C++ 構造体型のvector配列でエラーがでます

    構造体のvector配列を関数に渡しています。 以下のソースコードで、3点エラーがでます どのように変更すればよいですか? #include<stdio.h> #include<stdlib.h> #include<iostream> #include <vector> using namespace std; std::vector<int> v; typedef struct fukusosu{ int a; int b; }FUKUSOSU; int sort(vector<FUKUSOSU> v[], int N){ FUKUSOSU tmp; int j; for(int i = 0 ; i < N - 1 ; i++){ j = i ; for(int k = i + 1 ; k < N ; k++){ if(v[j].a > v[k].a){j = k;}//ここのaに対して、エラーがでます } tmp = v[j];//ここのイコールに対して、エラーがでます v[j] = v[i]; v[i] = tmp;//ここのイコールに対してエラーがでます } } int main(void){ int N; // 要素数 cin >> N; vector<FUKUSOSU> v(N); for(int i = 0; i < N; ++i){ cin >> v[i].a; cin >> v[i].b; } }

  • jpeg の DCT 変換がうまくいきません。

    jpeg の DCT 変換がうまくいきません。 jpegを作りたいのですが、DCT変換で詰まってしまいました。 よろしければ、ご教授いただけませんでしょうか? http://www.ann.hi-ho.ne.jp/jiro/assyuku2.htm のDCT変換の例を見て、プログラムを作ってみましたが、 変換例と同じ値に変換されませんでした。 作ってみたプログラムです。 #include <iostream> #include <stdio.h> #define _USE_MATH_DEFINES #include <math.h> using namespace std; void main(int argc, char** argv) {   double cu = 1.0;   double cv = 1.0;     double long sum = 0.0;      int before[8][8] ={     {57,49,44,39,33,28,23,22},     {55,45,39,33,28,21,21,19},     {55,44,37,31,20,17,17,16},     {58,44,37,29,17,15,16,14},     {66,46,31,22,16,14,12,10},     {71,49,32,24,14,12,21,19},     {69,50,30,22,12,4,-1,-2},     {62,42,25,17,7,1,-16,-16}      };   int after[8][8];   ZeroMemory(after,sizeof(int)*64);   for(int v =0; v < 8; v++)   {     if(v) cv =1.0;     if(!v) cv = 1 / sqrt(2.0);     for(int u = 0; u < 8; u++)     {       if(u) cu =1.0;       if(!u) cu = 1 / sqrt(2.0);       sum = 0.0;       for(int y = 0; y < 8; y++)       {         for(int x = 0; x < 8; x++)         {           double long a = cos((2 * x + 1)*u*M_PI/16) * cos(( 2 * y + 1)*v*M_PI/16);           double long d = before[x][y];           sum += d * a;         }       }       after[u][v] = int(cu*cv*sum/4);     }   }   for(int j = 0; j < 8; j++)   {     for(int i = 0; i < 8; i++)     {       cout << after[i][j] << ",";     }     cout << endl;   }   int b;   cin >> b ; }

  • C++で行列とベクトルの積を求める

    行列とベクトルの掛け算 y=Ax (A(3*3行列以上)とxを適当に初期化) を作成せよ これが分からないんですが誰か分かる人いませんか?下は行列の和と積をそれぞれ求めてるんですが、こんな感じになりそうなんですよね #include<iostream> using namespace std; int main() { double A[3][3]={{1,1,6},{5,3,2},{2,2,2}}; double B[3][3]={{4,1,3},{2,4,3},{5,9,2}}; double temp; int i,j,k; for(i=0;i<3;i++){ for(k=0;k<3;k++){ } } for(i=0;i<3;i++){ for(k=0;k<3;k++){ } } cout<<"和:A+B="<< '\n'; for(i=0;i<3;i++){ cout<<" { "; for(j=0;j<3;j++){ cout<< (A[i][j]+B[i][j]); if(j!=2) cout<<" , "; } cout<< " }" << '\n'; } cout<< '\n'; cout<<"積:A*B="<< '\n'; for(i=0;i<3;i++){ cout<<" { "; for(j=0;j<3;j++){ temp=0.0; for(k=0;k<3;k++) temp += A[i][k]*B[k][j]; cout<< temp; if(j!=2) cout<< " , "; } cout<< " }" << '\n'; } return 0; }

  • 並べ替えのプログラム

    整数を20個入力し、まずそのまま表示してその後大きい順に並べ替えて表示するプログラムを作っているのですが、最大値しか表示されません。多分for文の3重ループの中がおかしいと思うのですがよくわかりません。 #include <stdio.h> int main(int argc, char* argv[]) { int c,i,x,max; int sav = 0; int before[20]; int after[20]; int check[20] = {0}; printf("整数を20個入力してください: "); for(i = 0; i < 20; i++) { scanf("%d",&before[i]); } printf("\n"); printf("BEFORE\n"); for(i = 0; i < 20; i++) { printf("%d\n",before[i]); } printf("\n"); max = 0; for(c = 0; c < 20; c++) { for(x = 0; x < 20; x++) { for(i = 0; i < 20; i++) { if(before[i] > max && check[i] == 0) max = before[i]; sav = i; } if(check[sav] == 0) check[sav] = 1; after[19 - x] = max; } } printf("AFTER\n"); for(x = 0; x < 20; x++) { printf("%d\n",after[x]); } return 0; } よろしくお願いします。

  • C++での、素数の表を作成するプログラムについての質問です。

    C++での、素数の表を作成するプログラムについての質問です。 配列を使用して、2~71までの素数を表に埋め込みたいのです。 プログラム本体はここまで出来ているのですが、 素数を求める計算の方法がイマイチわかりません。 #include<iostream> #include <iomanip> using namespace std; #define N 20 int main() { int arry[N]; /********************************* ここでforを用いた反復で計算を行う **********************************/ /********************* 配列変数の内容を出力 *********************/ for(int i=0;i<N;i++) cout << "+--" ; cout << "+\n" ; for(int i = 0; i < N; i++ ) cout << "|" << setw(2) << arry[i] ; cout << "|\n" ; for(int i = 0; i < N; i++ ) cout << "+--" ; cout << "+\n" ; return 0; } for文を使用した反復構造でarry[N]に2~71までの数字をいれていきたいです。 お願いします。 なお、 int arry[N]={2,3,5,7…} や arry[0]=2; arry[1]=3; arry[2]=5; …のように入力してはいけないのです。

  • 配列のプログラムですが

    #include <iostream> using namespace std; int main() { int a[100],b=-9999; int i=0,j; do { cout << "整数値を入力してください\n"; cin >> a[i]; b += a[i]; i++; }while( a[i-1] != 9999); cout << b << '\n'; for(j=0;j<i-1;j=j+1) cout << a[j] * 3 << '\n'; return 0; } このプログラムってどんな計算をしてるんですか?誰か分かる人いますか 整数値を入れてくださいって出るだけなんですが

  • 数の大きさ

    C++初心者です。以下の様なプログラムで、合計を求めたいのですが、あまり桁数の大きい数だと、正確な値がでません。(20桁とか・・・)これは一体どういうことが考えられますか?//配列の全要素の合計を求める #include<iostream.h> int main(void) { int i; int a[5]={0}.; cout<<"5個の整数値を入力しましょう。 \n"; for(i=0; i<5; i++) { cout<<"No."<<i+1<<": "; cin>>a[i]; } int sum=0; for(i=0; i<5; i++) sum=sum+a[i]; cout<<"合計は"<<sum<<"です。\n"; return(0); }