ExcelマクロVBAサンプル集
1次元配列の並べ替え(バブルソート,クイックソート)

ExcelマクロVBAの実用サンプル、エクセルVBA集と解説
最終更新日:2019-07-21

1次元配列の並べ替え(バブルソート,クイックソート)


配列(1次元)の並べ替え方法について、バブルソートとクイックソートのサンプルになります。
元来エクセルには、ワークシートの並べ替え機能があります。
ワークシートにデータを書き出して、ワークシートの並べ替え機能を使えるのですが、
どうしても、配列をワークシートに途中で書き出すと言うのは面倒なものです。
そこで、配列を並べ替える必要が出てきます。
以下では、
Sheet1A1~A10000にランダムなデータを入れました。
これを(昇順に)並べ替えて、Sheet2 に出力しています。


バブルソート

ソートのアルゴリズムの中で、簡単で理解しやすいのは、バブルソートでしょう 。
バブルは「泡」のことで、並べ替えの過程でデータが下から上(上から下)へ移動する感じが、泡が浮かんでいく様に見えることからこの名前が付いているそうです。



Sub バブルソート(ByRef argAry() As Variant)
  Dim vSwap As Variant
  Dim i As Integer
  Dim j As Integer
  For i = UBound(argAry) To LBound(argAry) Step -1
    For j = LBound(argAry) To i - 1
      If argAry(j) > argAry(j + 1) Then
        vSwap = argAry(j)
        argAry(j) = argAry(j + 1)
        argAry(j + 1) = vSwap
      End If
    Next j
  Next i
End Sub

外側のFor~Nextの1回目が終わった時点で、配列の最後尾に最大値が来ます。
以下、2回目のループで配列の最後から2番目に2番目に大きいデータが来ます。
これの繰り返しになっています。

If argAry(j) > argAry(j + 1) Then
これを
If argAry(j) < argAry(j + 1) Then
とすれば、降順の並べ替えになります。

非常に単純ですが、処理時間がかかる事が難点です。
データ件数が、少なければ単純で良いでしょう。
では、実際の使い方と、その処理時間を見てみます。

Sub test1()
  Debug.Print Timer
  Dim ws1 As Worksheet
  Dim ws2 As Worksheet
  Dim myAry1()
  Dim myAry2()
  Dim i As Long
  Set ws1 = Worksheets("Sheet1")
  Set ws2 = Worksheets("Sheet2")
  myAry1 = ws1.Range("A1:A10000").Value
  'myAry1は2次元配列なのでmyAry2で1次元配列に変更
  ReDim myAry2(LBound(myAry1) To UBound(myAry1))
  For i = LBound(myAry1) To UBound(myAry1)
    myAry2(i) = myAry1(i, 1)
  Next
  '1次元バブルソート
  Call バブルソート(myAry2)
  'myAry2は1次元配列なのでmyAry1で2次元配列に変更
  For i = LBound(myAry2) To UBound(myAry2)
    myAry1(i, 1) = myAry2(i)
  Next
  ws2.Cells.Clear
  ws2.Range("A1:A10000").Value = myAry1
  Debug.Print Timer
End Sub

私の環境で 約2.9秒くらいかかりました。
1万件で2.9秒なら、遅いけど間でない時間ではないでしょうか、それでも件数的には限界でしょうね。

クイックソート

バブルソートよりもっと効率の良いソートアルゴリズムはないのか・・・
それがクイックソートになります。
クイックソートは一般的に最も高速だといわれてはいますが、
アルゴリズムとしてはいろいろな亜種があるらしいです。
ここでは、ごく一般的な方法を採用しています。
アルゴリズムの詳細は説明が長くなってしまいますので、専門に解説しているページを参照して下さい。



Sub クイックソート(ByRef argAry() As Variant, _
          ByVal lngMin As Long, _
          ByVal lngMax As Long)
  Dim i As Long
  Dim j As Long
  Dim vBase As Variant
  Dim vSwap As Variant
  vBase = argAry(Int((lngMin + lngMax) / 2))
  i = lngMin
  j = lngMax
  Do
    Do While argAry(i) < vBase
      i = i + 1
    Loop
    Do While argAry(j) > vBase
      j = j - 1
    Loop
    If i >= j Then Exit Do
    vSwap = argAry(i)
    argAry(i) = argAry(j)
    argAry(j) = vSwap
    i = i + 1
    j = j - 1
  Loop
  If (lngMin < i - 1) Then
    Call クイックソート(argAry, lngMin, i - 1)
  End If
  If (lngMax > j + 1) Then
    Call クイックソート(argAry, j + 1, lngMax)
  End If
End Sub

このアルゴリズムをすっきり理解するのは大変ですね。
検索時の二分探索と同じような考え方と言えば良いでしょうか。
配列の中央値との大小比較を行い、取り替える。
これを再帰プロージャーで、範囲を狭めながら繰り返しています。
これにより並べ替えを実現しています。
では、実際の使い方と、その処理時間を見てみます。

Sub test2()
  Debug.Print Timer
  Dim ws1 As Worksheet
  Dim ws2 As Worksheet
  Dim myAry1()
  Dim myAry2()
  Dim i As Long
  Set ws1 = Worksheets("Sheet1")
  Set ws2 = Worksheets("Sheet2")
  myAry1 = ws1.Range("A1:A10000").Value
  'myAry1は2次元配列なのでmyAry2で1次元配列に変更
  ReDim myAry2(LBound(myAry1) To UBound(myAry1))
  For i = LBound(myAry1) To UBound(myAry1)
    myAry2(i) = myAry1(i, 1)
  Next
  '1次元クイックソート
  Call クイックソート(myAry2, LBound(myAry2), UBound(myAry2))
  'myAry2は1次元配列なのでmyAry1で2次元配列に変更
  For i = LBound(myAry2) To UBound(myAry2)
    myAry1(i, 1) = myAry2(i)
  Next
  ws2.Cells.Clear
  ws2.Range("A1:A10000").Value = myAry1
  Debug.Print Timer
End Sub

私の環境で 約0.02秒~0.04秒です。
やはり断然はやいですね。

最後に

数百件程度の配列なら、バブルソートでもよいですが、
それ以上になるなら、やはりクイックソートが好ましいでしょう。

今回の実行例でもそうですが、
やはり、配列は2次元になる場合が多いです。
そこで、次回は、
2次元配列の並べ替え
配列(2次元)の並べ替え方法についてバブルソートとクイックソートのサンプルになります。2次元配列の並べ替えと言えばまさにワークシートの並べ替え機能になります。本来はワークシートにデータを書き出してワークシートの並べ替え機能を使えば良いのですがしかしどうしても配列をワークシートに処理途中で書き出すと言うのは面倒なものです。



同じテーマ「マクロVBAサンプル集」の記事

1次元配列の並べ替え(バブルソート,クイックソート)
2次元配列の並べ替え(バブルソート,クイックソート)
Dir関数で全サブフォルダの全ファイルを取得
順列の全組み合わせ作成と応用方法


新着記事NEW ・・・新着記事一覧を見る

Byte配列と文字コード関数について|VBA技術解説(8月20日)
PowerQueryの強力な機能をVBAから利用する方法|VBA技術解説(8月4日)
練習問題31(セル結合を解除して値を埋める)|VBA練習問題(7月30日)
練習問題30(マトリックス→リスト形式)|VBA練習問題(7月25日)
Applicationを省略できるApplicationのメソッド・プロパティ一覧|VBA技術解説(7月22日)
コレクション(Collection)の並べ替え(Sort)に対応するクラス|VBA技術解説(7月20日)
CSVの読み込み方法(ジャグ配列)|VBAサンプル集(7月15日)
その他のExcel機能(グループ化、重複の削除、オートフィル等)|VBA入門(7月14日)
オートフィルタ退避回復クラスを複数シート対応させるVBAクラス|VBA技術解説(7月6日)
オートフィルタを退避回復するVBAクラス|VBA技術解説(7月6日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.RangeとCellsの使い方|ExcelマクロVBA入門
4.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
5.変数とデータ型(Dim)|ExcelマクロVBA入門
6.繰り返し処理(For Next)|ExcelマクロVBA入門
7.マクロって何?VBAって何?|ExcelマクロVBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.ひらがな⇔カタカナの変換|エクセル基本操作
10.空白セルを正しく判定する方法(IsEmpty,IsError,HasFormula)|VBA技術解説



  • >
  • >
  • >
  • 1次元配列の並べ替え(バブルソート,クイックソート)

  • このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


    記述には細心の注意をしたつもりですが、
    間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
    なお、掲載のVBAコードは自己責任で使ってください。万一データ破損等の損害が発生しても責任は負いません。




    このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
    本文下部へ