第12講 様々な並び替えの方法
第11話 setによる並び替え

この話ではsetによる並び替えを紹介しましょう。
setを利用するためには、インクルードファイル<set>をインクルードしておく必要がありますので、
プログラム冒頭に#include<set>;  とusing namespace std; を入れておく必要があります。
#pragma once
#include<set>
using namespace std;
    ・
    ・
    ・
皆さん、まず次のダウンロード用ファイルForm8.hをダブルクリックして開いて下さい。
そして、上から下までドラッグして下のように全範囲を指定し、

                 ・
                 ・
                 ・

コピー(右クリック→コピー)してください。
次に、Visual C++を起動して、
新しいプロジェクトをクリックして,名前に『並び替え第6話用』と入力して、
OKボタンを押します。
並び替え第6話用が現れたら、
Form1.hを右クリックして、コードの表示を
クリックします。Form1.hのコードが出てきますので、それを全範囲を下のようにドラッグで指定します。

                 ・
                 ・
                 ・

右クリックして、貼り付けを選択してください。
そうすると、コード全体がダウンロードしたForm8.hと同じになります。
(コピーペーストうまく利用して、Form1.hのソース全文がForm8.hと同じになるようにしてください。)

これで、第6話で作ったソフトが完成します。ビルドすると、次のソフトが立ち上がるはずです。

今回は、これをset使って改良します。

まず、前に使用したBr(a,n);とNb(a,n); は今回使用しませんので、
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
  int a[N];
  int n=int::Parse(textBox1->Text);
  ds(a,n);
  if(n>9)Br(a,n);
  Nb(a,n);

}
void Br(int* p,int n){
     ・
     ・
     ・
}
void Nb(int* p,int n){
     ・
     ・
     ・
}


のピンクの部分はすべて削除してください。
さらに、デザイナーに切り替えて、

赤で囲んであるところをすべて削除してください。

最後、ソースを次のように改良します。
#pragma once
#include<stdlib.h>
#include<set>      //setのために必要
using namespace std; //setのために必要

const int N=30;
namespace 並び替え第6話用 {
      ・
      ・
      ・
#pragma endregion
  private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
          int a[N];
          int n=int::Parse(textBox1->Text);
          ds(a,n);
          set<int> s;
          int i;
          String^ w=L"";
          for(i=0;i<n;i++)s.insert(a[i]);
          for(set<int>::iterator i=s.begin();i!=s.end();it++){
             w+=(*i).ToString()+L" ";
          }
          textBox5->Text=w;

        }
        void ds(int* p,int n){
          int i;
          String^ w=L"";
          for(i=0;i<n;i++){
            p[i]=rand() % 100;
              w+=(p[i]).ToString()+L" ";
           }
          textBox2->Text=w;
        }

  };
}
それで、ビルドして、データ数のところの例えば30(これは上限)といれて実行ボタンを押すと

のように並び替えが成功しています。

setについて解説しましょう。
set<変数型> 変数名;
で、<>内で指定している変数型の変数を収納する配列に相当するものの宣言ができます。
普通の配列は、
int a[20];
のように要素数が決まっていますが、
set<int> s;
で宣言された配列に相当するsはいくらでも代入できます。
代入する度に、要素数が増えていき、、
しかも、出力する際には昇順になっているという特別な配列のようなものです。
代入はs.insert(20); のようにします。
これで配列に相当するsに20が代入されました。
for(i=0;i<n;i++)s.insert(a[i]); ならばsにa[0]からa[n-1]までが代入されます。

int a[20]; と宣言した配列でも
次のように出力することも可能でしたね。
int* i;
for(i=a;i<a+n;i++){
  w+=(*i).ToString()+L" ";
}
それと似ているのが
for(set<int>::iterator i=s.begin();i!=s.end();it++){
  w+=(*i).ToString()+L" ";
}
です。set<int>::iterator i はiがset<int>型のイテレータであると宣言しています。
これは配列の場合の*iのiに対応するものです。
ポインタはiが変数のアドレス、*iがそのアドレスに代入されている値
であったように、イテレータもiはアドレス、*iはそのアドレスに代入されている値です。
i=s.begin(); でset型配列sの最初のアドレスを取得しています。
そして、i!=s.end();でset型配列sの最後の一つ手前のアドレスを取得しています。
一つ手前である理由は、

内容 9 6 7 5
アドレス 0000 0001 00002 0003 0004

先にアドレスが割り振られ、内容が入るように待機しているからです。
だから、一つ手前のアドレスということになります。


つまり、setでは変数名.insert(値)で代入が行われ、代入する度に自動的に並び替えが行われているのです。
出力するときには
for(set<int>::iterator i=s.begin();i!=s.end();it++){
  w+=(*i).ToString()+L" ";
}

のようにイテレータを使います。

第12講第10話へ 第12講第11話へ



vc++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ