ExcelマクロVBAサンプル集 | 1次元配列の並べ替え(バブルソート,クイックソート) | Excelマクロの実用サンプル、エクセルVBA集と解説



最終更新日:2013-06-14

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


配列(1次元)の並べ替え方法について、バブルソートとクイックソートのサンプルになります。

元来エクセルには、ワークシートの並べ替え機能があります。


ワークシートにデータを書き出して、ワークシートの並べ替え機能を使えるのですが、

どうしても、配列をワークシートに途中で書き出すと言うのは面倒なものです。

そこで、配列を並べ替える必要が出てきます。

以下では、

Sheet1A1〜A10000にランダムなデータを入れました。

これを(昇順に)並べ替えて、Sheet2 に出力しています。

バブルソート

ソートのアルゴリズムの中で、簡単で理解しやすいのは、バブルソートでしょう 。

バブルは「泡」のことで、並べ替えの過程でデータが下から上へ移動する感じが、泡が浮かんでいく様に見えることからこの名前が付いています。
Sub BubbleSort1(ByRef argAry() As Variant)
  Dim vSwap As Variant
  Dim i As Integer
  Dim j As Integer
  For i = LBound(argAry) To UBound(argAry)
    For j = UBound(argAry) To i Step -1
      If argAry(i) > argAry(j) Then
        vSwap = argAry(i)
        argAry(i) = argAry(j)
        argAry(j) = vSwap
      End If
    Next j
  Next i
End Sub

外側のFor〜Nextの1回目が終わった時点で、配列の先頭に最小値が来ます。
以下、2回目のループで配列の2番目に2番目に小さいデータが来ます。
これの繰り返しになっています。

If argAry(i) > argAry(j) Then
これを
If argAry(i) < argAry(j) 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 BubbleSort1(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

私の環境で 約15秒かかりました。

1万件で15秒なら、ぎりぎり限度内でしょうか、それでも件数的には限界でしょうね。

では、もっと効率の良いソートアルゴリズムはないのか・・・

それがクイックソートになります。

クイックソート

クイックソートは一般的に最も高速だといわれてはいます。

アルゴリズムとしてはいろいろな亜種があるらしいです。

ここでは、ごく一般的な方法を採用しています。

アルゴリズムの詳細は、説明が長くなってしまいますので、専門に解説しているページを参照して下さい。
Sub QuickSort1(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 QuickSort1(argAry, lngMin, i - 1)
  End If
  If (lngMax > j + 1) Then
    Call QuickSort1(argAry, j + 1, lngMax)
  End If
End Sub

このアルゴリズムをすっきり理解するのは大変ですね。

検索時の二分探索と同じような考え方と言えば良いでしょうか。

配列の中央値との大小比較を行い、取り替える。

これを再帰プロージャーで、範囲を狭めながら繰り返しています。

これにより並べ替えを実現しています。

では、実際の使い方と、その処理時間を見てみます。
Sub test2() '0.13
  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 QuickSort1(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.15秒です。

やはり断然はやいですね。

数百件程度の配列なら、バブルソートでもよいですが、

それ以上になるなら、やはりクイックソートが好ましいでしょう。


今回の実行例でもそうですが、

やはり、配列は2次元になる場合が多いです。

そこで、次回は、

2次元配列の並べ替え




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

2次元配列の並べ替え(バブルソート,クイックソート)
Dir関数で全サブフォルダの全ファイルを取得

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

Excelファイルを開かずにシート名をチェック|ExcelマクロVBAサンプル集(3月23日)
数式の参照しているセルを取得する|ExcelマクロVBAサンプル集(3月18日)
CSVの読み込み方法(改の改)|ExcelマクロVBAサンプル集(3月17日)
変数とプロシージャーの命名について|ExcelマクロVBA技術解説(2月12日)
ファイルの一覧取得・削除(File)|Google Apps Script入門(1月24日)
フォルダの一覧取得・作成・削除(Folder)|Google Apps Script入門(1月24日)
フォルダとファイルを扱う(DriveApp)|Google Apps Script入門(1月24日)
スプレッドシートが非常に遅い、高速化するには|Google Apps Script入門(1月17日)
画像のトリミング(PictureFormat,Crop)|ExcelマクロVBAサンプル集(12月27日)
シート保護|Google Apps Script入門(12月24日)

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

1.最終行の取得(End,Rows.Count)|ExcelマクロVBA入門
2.RangeとCellsの使い方|ExcelマクロVBA入門
3.徹底解説(VLOOKUP,MATCH,INDEX,OFFSET)|エクセル関数超技
4.Range以外の指定方法(Cells,Rows,Columns)|ExcelマクロVBA入門
5.セルの参照範囲を可変にする(OFFSET,COUNTA,MATCH)|エクセル関数超技
6.セルのコピー&値の貼り付け(PasteSpecial)|ExcelマクロVBA入門
7.変数とデータ型(Dim)|ExcelマクロVBA入門
8.ひらがな⇔カタカナの変換|エクセル基本操作
9.CSVの読み込み方法|ExcelマクロVBAサンプル集
10.VBAのFindメソッドの使い方には注意が必要です|ExcelマクロVBA技術解説



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

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


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

    ↑ PAGE TOP