ページ 5 / 8
構造体定義について
Posted: 2005年10月16日(日) 09:18
by omasu
お世話になります。
arさん
早速の対応ありがとうございます。
私も動的(静的?)な確保にチャレンジをしておりました。
しかし、このレベルのコードは、手直しに失敗すると愛機がすぐ迷宮入りしてしまう
危険な領域であることを実感しております。
マティさんやイグトランスさんのコードのように、
あらかじめ最大ソート件数を定義(Const)しておき、領域(配列)を確保
データを取り込む際に、データ件数を取得し、ソート領域を指定する、
そのように変更したかったのですが、私の実力では、まだまだのようです。
(実際ソート処理をする場合は、大まかな件数はわかっていても、正確に何件かはわからないため。)
arさんのコード本体を利用し、シェル4を組み込み実行してみました。
実行時間が10万件で7.721秒から1.522秒と格段に早くなりました。
恐れ入りました。m(_ _)m
構造体に大変興味が湧いてきました。これから勉強してみます。
追伸:arさんの「マージソート その2」について
実行時間の測定のために100万件の入力データを固定し、そのうち何件をソートするか入力する。
斬新なアイデアに感銘しております。
実行時間比較では件数に対応した入力ファイル名をいちいち直し、コンパイルしていました。
Input文の入力の変わりに、データカウントで代用するという手段も考えていますが、
今後の実用的な処理にするために、私が挫折中の静的確保についてもご尽力いただければ幸いです。
追伸2:私の環境だと50万件までのソートはできるのですが、
常駐ファイルを全て落とし、メモリーを掃除した後だと、時間が計れます。
しかし、いったんディスクがカサカサし始めると、とたんに時間がかかり、計測失敗となります。
実行時間の安定性のため、10万件までとしています。
arさんの100万件の使用メモリが23MBということ(動的な確保の場合)
一段と速度が速くなっていることから、50万件の復活の可能性があるかもしれません。
RE:マージソート その2(再送)
Posted: 2005年10月16日(日) 21:02
by omasu
お世話になります。
arさんの深い考えに今頃気づきました。
対応済みだったのですね
(しかも動的に)(メモリも最小)
Input "record number =?",nをコメントアウト
If n<1 Or n>rcd_max Then n=rcd_maxをコメントアウト
を
n=rcd_maxにしました。
そのままデータ件数を実行できました。
ありがとうございます。
Posted: 2005年10月16日(日) 21:18
by 河川屋
10/12の記事で気になったのがあるので2言。
>安定性を求める場合はマージ?(データのならびに左右されない?)。
安定性を、
データの並びが変わってもソート時間一定
の意味で使っているようですが、安定性の意味が違います。
・同値のデータがあった場合、元の順序が保持される
というのが安定なソートで、そうならないのが不安定なソートです。
たとえば、1桁の整数
314一592を並べ換えると、
95432一1となります(1と一は元の位置確認のための区別。)が、
このとき、1一となる保証があるのが安定なソート。
ただし、データに細工をする(元の要素番号を覚えておき、同値なら要素番号で判定する)といった方法はとらないものとして
安定かどうかを見ます。
単純挿入、バブル、マージは安定、選択、シェル、ヒープ、クイックは不安定。
>トーナメント法 推定で何個も作成、なぜか単純選択法になってしまう。
これは、最初に優勝者を決めたときに、「誰とと誰が対戦しどちらが勝ったか」
を情報として保存する必要があります。保存する方法は、例えば2分木。
2位決めは、保存したデータを使って対戦済データを端折ります。
ヒープソートも、対戦方法を覚えておくやりかたの1つで、親ノードと子ノード
の関係がそのまま勝敗になるようにデータを入れ替えていき、ヒープが完成した
時点で優勝者および対戦表が完成しているのと等価です。
で、2分木を使ったソートというのも実在します。
(ヒープソートと二分木ソートは、全くの別もの。)
これは、
・データを足していく途中でもデータを検索する必要がある場合
(例えば、文章中の単語の種類と数のカウント。同じ単語は登録しない。)
に用いられます。
具体例はこちら。
http://www.rs.kagu.sut.ac.jp/~infoserv/index.html
平成11年度秋期第2種情報処理試験午後問7。(C言語、再帰あり)
大まかな動きは、
既存データの右に大きいデータを、左に小さいデータをブラ下げていく。
ブラ下げ終わったら、木をたどってデータを取り出す
(というか、Indexの作り方はこちらが普通の方法であり、順位をIndexにするほうが用途としては特殊。)
であり、トーナメント法式ではないです。
処理時間はnlognだから、クイックやヒープと同等のオーダーのソート法ですが、
既ソート済/逆順データに対してはボロボロになります。
安定性について
Posted: 2005年10月16日(日) 21:47
by omasu
お世話になります
久々のありがたいご意見番(失礼しました)の登場に感謝をしております。
当初の考えはそのとおりです。
過去ログにおいて
時間: 2005年09月24日(土) 20
題名: ありがとうございます。
マージ=安定性を求める場合はマージ?(キーが同一の場合、最初のデータが先にくる? fifo)
という記述をしていたのですが、
皆様のありがたい討論の中に
時間: 2005年09月29日(木) 02
題名:なし
>クイックソートは速いアルゴリズムで非常に美しいですが、
>安定じゃないのだけが欠点ですね。
クイックソートは、「n^2の時間がかかる数列が存在する」というのが最大の欠点
という記述により、
マージ=安定性を求める場合はマージ?(データのならびに左右されない?)。
というように考え方が変わってしまいました。
申し訳ありません。
もう少し、考え方をを皆様に確認をするよう、改めます。
トーナメント法、ヒープ、2分木も勉強していきます。
相対編成ファイルや、直接編成ファイルの概念も使っていこうと思います(シノニムに注意)
ラディックスソート
Posted: 2005年10月19日(水) 18:45
by ar
標記の件、C言語アルゴリズム辞典より写してみました。
データの入出力などは、以前投稿のマージソートのコードを流用してください。
その際、以下の点変更願います。
1) work = New [ELM(n) \ 2 + 1] CSVSORT → work = New [ELM(n)] CSVSORT
2) mergesort_str(0, n - 1, data) → radixsort(n, 10, data, work)
3) 出力ファイル名、Print文などでmergeと記載されているところ
パフォーマンスは比較文字数と件数に比例するので、今回の10文字程度の比較なら相当速いみたいです。
手元の環境で、マージソートの半分近い時間で終了しています。
ただし、確保する配列数が増えるのでメモリの消費量は増えます(100万件時で約31MBでした)。
また、lstrcmp()を用いた比較と異なる順序を与えるので注意が必要です。
コード: 全て選択
'ラディックスソート
' n : データ数
' length : データの文字長
' a : データ配列(0~n-1)
' work : 展開用配列(0~n-1)
Sub radixsort(n As Long, length As Long, a As *CSVSORT, work As *CSVSORT)
Const UCHAR_MAX = 255
Dim i As Long
Dim j As Long
Dim count[UCHAR_MAX] As Long
j = length - 1
Do
'count配列を初期化
i = 0
Do
count = 0
i = i + 1
Loop Until i > UCHAR_MAX
'
i = 0
Do
count[a.keystr[j]] = count[a.keystr[j]] + 1
i = i + 1
Loop While i < n
'
i = 1
Do
count = count + count
i = i + 1
Loop Until i > UCHAR_MAX
'
i = n - 1
Do
count[a.keystr[j]] = count[a.keystr[j]] - 1
work[count[a.keystr[j]]].keystr = a.keystr
work[count[a[i].keystr[j]]].info = a[i].info
i = i - 1
Loop Until i < 0
'
i = 0
Do
a[i].keystr = work[i].keystr
a[i].info = work[i].info
i = i + 1
Loop While i < n
j = j - 1
Loop Until j < 0
End Sub
Re: ラディックスソート
Posted: 2005年10月19日(水) 21:38
by omasu
>ラディクスソートの件
> 手元の環境で、マージソートの半分近い時間で終了しています。
> ただし、確保する配列数が増えるのでメモリの消費量は増えます(100万件時で約31MBでした)。
ありがとうございます!(~O~)。早速実行してみます。
今までZgockさんの情報を受けるまで聞いたことのないソートでした。
今、BytePtr型が、なぜ4文字なのか悩んでいます。
バケツソート文字列版も作成途中ですが、(あれこれやりすぎて脳みそスタック不足)(◎!◎)
「頭から1文字ずつバケツ化していく」、それと類似をしているのでしょうか?
そうであればかなわないかな?
やはりバケツは「プライマリーキーの数字で、なおかつ範囲が限られている場合」だと一番早い。
[1から1000の単一の数値をばらばらにし、それをソートする場合等」1パスでソート完了!
作成中バケツの問題点として頭の数文字が全て同じ場合に無駄な時間を費やす事でしょうか、
また、キーが全て同一の場合は、よくわかりませんが。
実用的ソートロジックを将来構想として、キー列指定他、
可変長文字列化、外部パラメータ指定など(どこから?)、
いろいろな、構想をしていきたいと思います。
他の、どの言語よりすばらしくなること
アクティブベーシックの継承資産となれば幸いとおもっています。
ソートロジック大会
Posted: 2005年10月23日(日) 18:40
by omasu
お世話になります。
arさんのラディックスソートの実行結果について
どこまで行くのか実行速度 (o!o)・・・(ウルトラマンデハナイデス)
近況報告:
ソートキーをハッシングを使ってテーブルにセットすることに失敗しました。
10桁の文字キーを数値化すると30桁が必要です。(QWordでもだめ)
それをデータ件数のテーブルに圧縮セットすると、シノニム(コリジョン)が多発
計算ロジックとコリジョンの回避ロジックに時間を費やし、かえって遅くなりました。
ここをクリックすると実行速度比較が表示されます。 [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]実行環境 (ActiveBasic Ver.4.10~4.10.01)
(Cpu Pentium4 周波数2.66GHz メモリ256MByte)
テストcsvファイル 5桁のランダム数字も5桁のランダム文字もソート可能なロジック キー列(1列目と2列目を連結) データ列数(26列)
作成者 ソート名称 1,000 5,000 10,000 50,000 100,000 記事
arさん ラディックス 0.010 0.030 0.060 0.250 0.551 ラディックス最速
arさん マージ 0.010 0.060 0.120 0.411 0.892 マージ最速
マティさん クイック改4(800万件) 0.050 0.080 0.120 0.821 6.649 クイック最速
〃 〃 800万件 2080.631秒 最大件数ソート可能
イグトランスさん クイック 0.040 0.241 0.521 3.235 6.709
omasu シェル4(0.8975+0.45) 0.040 0.261 0.591 3.555 7.721 シェル最速
omasu シェル3(0.8975+¥3) 0.061 0.280 0.601 4.566 9.163
河川屋さん コム(挿入法) 0.070 0.411 0.901 5.958 12.308 コム最速
omasu シェル2(クヌース大大先生) 0.040 0.320 0.701 4.847 12.738
河川屋さん シェル(クヌース大先生) 0.170 0.821 2.003 13.079 30.964
omasu 単純挿入法(バイナリサーチ) 0.080 0.811 2.895 65.595 261.576 単純挿入法最速
omasu シェル(選択法) 0.381 4.747 13.770 177.305 ―――――――
omasu 単純挿入法 0.862 18.778 77.031 ――――――― ―――――――
omasu シェーカー(バブル) 1.191 27.880 116.237 ――――――― ――――――― シェーカー最速
omasu 単純選択法 1.432 36.603 143.632 ――――――― ――――――― 単純選択法最速
omasu バブル 1.482 38.215 150.567 ――――――― ――――――― バブル最速
トーナメント法 推定で何個も作成、なぜか単純選択法になってしまう。
ヒープ 難しいのかな?
テストcsvファイル 5桁のランダム数字をソート可能なロジック キー列(1列目と2列目を連結) データ列数(26列)
作成者 ソート名称 1,000 5,000 10,000 50,000 100,000 記事
河川屋さん (PJ)クイック(改2) 0.080 0.140 0.271 0.801 1.142 クイック最速
河川屋さん (PJ)クイック(改1) 0.020 0.130 0.170 0.732 1.151 クイック最速
河川屋さん (PJ)クイック(ノーマル版) 0.130 0.160 0.210 0.831 1.192 クイック最速
マティさん (PJ)コーム 0.010 0.060 0.120 0.581 1.643 コーム最速
追伸:arさんがクイックソートを作るとどうなるのでしょうか?
クイックソート
Posted: 2005年10月25日(火) 22:22
by ar
残念ながら・・・というより当然ながら劇的に速くはなりません。
クイックソートは代表的なソートアルゴリズムですし、そのソースコードも書籍などで広く紹介されています。たぶん、これまで投稿された方々もそういったものを見て勉強し、コードを組んでいるはずです。当然、私もそうですから、クイックソート自体に差は無いと考えます。実際、投稿したものは「クイックソート改2」に相当しますが、1万件までのソート実行時間が他に比べて特に速いということはありません。ただし、5万件以降のソート時間には差が出てきます。これはどちらかというと、キー比較の仕方とかスワップ関係などアルゴリズム以外の要因が絡んでいるのではないでしょうか?
追伸1
クイックから挿入法への閾値(THRESHOLD)は、10~15くらいが最速でした。
追伸2
私が引用元にしていたのは、「C言語による最新アルゴリズム事典」(奥村晴彦著 技術評論社)です。
これはソースコードだけなら筆者のHPもしくはvectorで公開されているはずです。
BASICに慣れた身ではC言語の読み下しに骨が折れましたが、それだけの価値はあると思います。
もしユーザー参加型のプロジェクトができるようになったら、これのActiveBasicへの移植を提案したいですね。
コード: 全て選択
'work配列いりません
'quicksort_str(ELM(n), data)で実行してください
'クイックソート(スタック配列使用)
' n : 添え字の最大値
' a : 配列のポインタ
Const THRESHOLD = 10 '挿入ソートに切り替える境界値
Const STACKSIZE = 32 'たかだか Long のビット数程度(>log2Nの数であること)
Sub quicksort_str(n As Long, a As *CSVSORT)
Dim i As Long
Dim j As Long
Dim left As Long
Dim right As Long
Dim middle As Long
Dim p As Long
Dim leftstack[STACKSIZE] As Long
Dim rightstack[STACKSIZE] As Long
Dim x As CSVSORT '中間値
Dim tmp As CSVSORT '入れ替え用
left = 0
right = n
p = 0
While 1
If right - left <= THRESHOLD Then
If p = 0 Then Exit While
p = p - 1
left = leftstack[p]
right = rightstack[p]
End If
middle = (left + right) \ 2 '(first + last) / 2
x.keystr = a[middle].keystr
x.info = a[middle].info
i = left
j = right
While 1
While lstrcmp(a.keystr, x.keystr) < 0
i = i + 1
Wend
While lstrcmp(x.keystr, a[j].keystr) < 0
j = j - 1
Wend
If i >= j Then Exit While
tmp.keystr = a.keystr
tmp.info = a.info
a.keystr = a[j].keystr
a.info = a[j].info
a[j].keystr = tmp.keystr
a[j].info = tmp.info
i = i + 1
j = j - 1
Wend
If i - left > right - j Then
If i - left > THRESHOLD Then
leftstack[p] = left
rightstack[p] = i - 1
p = p + 1
End If
left = j + 1
Else
If right - j > THRESHOLD Then
leftstack[p] = j + 1
rightstack[p] = right
p = p + 1
End If
right = i - 1
End If
Wend
inssort_str(n, a)
End Sub
'挿入ソート
' n : 添え字の最大値
' a : 配列のポインタ
Sub inssort_str(n As Long, a As *CSVSORT)
Dim i As Long
Dim j As Long
Dim x As CSVSORT
i = 1
Do
x.keystr = a.keystr
x.info = a.info
j = i - 1
While j >= 0
If lstrcmp(a[j].keystr, x.keystr) <= 0 Then Exit While
a[j + 1].keystr = a[j].keystr
a[j + 1].info = a[j].info
j = j - 1
Wend
a[j + 1].keystr = x.keystr
a[j + 1].info = x.info
i = i + 1
Loop Until i > n
End Sub
お詫び
Posted: 2005年10月27日(木) 18:11
by zgock
私の発言のtypoと言い間違いから混乱をさせたようで申し訳ありません。
ラディックスソートについてもヒントを出した程度で、
実装はarさんにおまかせする格好になってしまいました。
ご指摘のとおりヒープソートは「安定したソート」ではありません。
言いたかったのは
「データ内容による速度のばらつきがクイックソートほど極端ではない」
という点でした。
今回のようにソートキーが固定長でかつ短い場合、
ラディックスは有効だろうなと思いましたが、
ここまで差が出るとは思いませんでした。
ラディックスはキーの長さが速度に単純比例しますから、
キーの長さが現在の10倍を越えるとクイックと逆転すると思います。
バケツほどではないですが、ワークを大量に使用しますので、
ワークが確保できる程度の件数で、かつキーの長さが有限:ラディックス
ワークが確保できない程度で、キーの長さが有限:マージ等
キーの長さが長いか不定:クイック等比較系ソート
という使い分けをするといいのかな、と感じました。
#奥村先生の「アルゴリズム辞典」は名著だと思います。
#(最初のPascal版、C版、最新のJava版と全部持ってますw)
ありがとうございます。
Posted: 2005年10月27日(木) 22:08
by omasu
お世話になります。
zgockさん、ありがとうございます。
私の勝手な判断と、このような丁寧なメッセージに恐縮しております。
もっといろいろなロジックがあるぞと、示唆していただければ幸いです。
arさん、ありがとうございます。
クイックソートを実行してみました。(まだまだ、コード全体がないと苦労しますが(^ ^;)
私がまだ未到達なクイックソート、劇的なスピードアップもかなり期待してしまいました。(^ ^)なぜ?!
解明にはまだまだ時間がかかりそうです。申し訳ありません。
コームソートもしっかり学習しました。
もっと早いコームロジックを模索中です。(完成度が高く、早くする場所がない?)(_ _)(突っ込まれるかな)
ここをクリックすると実行速度比較が表示されます。 [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]実行環境 (ActiveBasic Ver.4.10~4.10.01)
(Cpu Pentium4 周波数2.66GHz メモリ256MByte)
テストcsvファイル 5桁のランダム数字も5桁のランダム文字もソート可能なロジック キー列(1列目と2列目を連結) データ列数(26列)
作成者 ソート名称 1,000 5,000 10,000 50,000 100,000 記事
arさん ラディックス 0.010 0.030 0.060 0.250 0.551 ラディックス最速
arさん マージ 0.010 0.060 0.120 0.411 0.892 マージ最速
arさん クイック 0.010 0.050 0.110 0.410 0.952 クイック最速
マティさん クイック改4(800万件) 0.050 0.080 0.120 0.821 6.649
〃 〃 800万件 2080.631秒 最大件数ソート可能
イグトランスさん クイック 0.040 0.241 0.521 3.235 6.709
omasu シェル4(0.8975+0.45) 0.040 0.261 0.591 3.555 7.721 シェル最速
omasu シェル3(0.8975+¥3) 0.061 0.280 0.601 4.566 9.163
河川屋さん コム(挿入法) 0.070 0.411 0.901 5.958 12.308 コム最速
omasu シェル2(クヌース大大先生) 0.040 0.320 0.701 4.847 12.738
omasu コーム(ノーマル) 0.121 0.450 1.032 6.359 13.620
河川屋さん シェル(クヌース大先生) 0.170 0.821 2.003 13.079 30.964
omasu 単純挿入法(バイナリサーチ) 0.080 0.811 2.895 65.595 261.576 単純挿入法最速
omasu シェル(選択法) 0.381 4.747 13.770 177.305 ―――――――
omasu 単純挿入法 0.862 18.778 77.031 ――――――― ―――――――
omasu シェーカー(バブル) 1.191 27.880 116.237 ――――――― ――――――― シェーカー最速
omasu 単純選択法 1.432 36.603 143.632 ――――――― ――――――― 単純選択法最速
omasu バブル 1.482 38.215 150.567 ――――――― ――――――― バブル最速
トーナメント法 ただいま勉強中です。
ヒープ ただいま勉強中です。
テストcsvファイル 5桁のランダム数字をソート可能なロジック キー列(1列目と2列目を連結) データ列数(26列)
作成者 ソート名称 1,000 5,000 10,000 50,000 100,000 記事
河川屋さん (PJ)クイック(改2) 0.080 0.140 0.271 0.801 1.142 クイック最速
河川屋さん (PJ)クイック(改1) 0.020 0.130 0.170 0.732 1.151 クイック最速
河川屋さん (PJ)クイック(ノーマル版) 0.130 0.160 0.210 0.831 1.192 クイック最速
マティさん (PJ)コーム 0.010 0.060 0.120 0.581 1.643 コーム最速
コームソートロジック(ノーマル)のコードも掲示します。
母体はイグトランスさんのコードです。
イグトランスさんの美しく、解りやすい(私にはまだまだ難しい)、高度なロジックを愛用しています。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Sub Sort(ByVal S As Long,ByVal E As Long)
Dim Bunkatu As Long
Dim P As Long
Bunkatu=E
Do ' コームソート
Bunkatu=(Bunkatu*10)\13
For i=S To E-Bunkatu
If lstrcmp(KeyTable[Index],KeyTable[Index[i+Bunkatu]])>0 Then
Swap(Index,Index[i+Bunkatu])
EndIf
Next i
Loop Until Bunkatu<1
Do ' バブルソート
P=0
For i=E To S+1 Step -1
If lstrcmp(KeyTable[Index],KeyTable[Index[i-1]])<0 Then
Swap(Index,Index[i-1])
P=i
EndIf
Next i
S=S+1
Loop Until P=0
End Sub
追伸:私が作るとN88風で懐かしくなってしまいます。
中間結果のご報告について
Posted: 2005年11月01日(火) 23:03
by omasu
お世話になります。
コームソートの模索により、すこし早くなりました。
クシ(コーム)関心するネーミングがやっと理解できました。
最初は荒いクシですき、次は少し細かいクシですき
コームソートのギャップの減らし方を例のごとく、1万件のソートを3千回実施、
最速値は13.855~14.164でした。
単純にギャップの減らし方を、件数を1.3で割る→件数を1.4で割るに変更すればすこし早くなると考えます。
ここをクリックすると実行速度比較が表示されます。 [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]実行環境 (ActiveBasic Ver.4.10~4.10.02)
(Cpu Pentium4 周波数2.66GHz メモリ256MByte)
テストcsvファイル 5桁のランダム数字も5桁のランダム文字もソート可能なロジック キー列(1列目と2列目を連結) データ列数(26列)
作成者 ソート名称 1,000 5,000 10,000 50,000 100,000 記事
arさん ラディックス 0.010 0.030 0.060 0.250 0.551 ラディックス最速
arさん マージ 0.010 0.060 0.120 0.411 0.892 マージ最速
arさん クイック 0.010 0.050 0.110 0.410 0.952 クイック最速
マティさん クイック改4(800万件) 0.050 0.080 0.120 0.821 6.649
〃 〃 800万件 2080.631秒 最大件数ソート可能
イグトランスさん クイック 0.040 0.241 0.521 3.235 6.709
omasu シェル4(0.8975+0.45) 0.040 0.261 0.591 3.555 7.721 シェル最速
omasu シェル3(0.8975+¥3) 0.061 0.280 0.601 4.566 9.163
omasu コーム2(挿入法1.4) 0.091 0.391 0.822 4.767 10.705 コ-ム最速
河川屋さん コム(挿入法) 0.070 0.411 0.901 5.958 12.308
omasu シェル2(クヌース大大先生) 0.040 0.320 0.701 4.847 12.738
omasu コーム2(バブル1.4) 0.130 0.400 0.922 5.578 12.899
omasu コーム(ノーマル) 0.121 0.450 1.032 6.359 13.620
河川屋さん シェル(クヌース大先生) 0.170 0.821 2.003 13.079 30.964
omasu 単純挿入法(バイナリサーチ) 0.080 0.811 2.895 65.595 261.576 単純挿入法最速
omasu シェル(選択法) 0.381 4.747 13.770 177.305 ―――――――
omasu 単純挿入法 0.862 18.778 77.031 ――――――― ―――――――
omasu シェーカー(バブル) 1.191 27.880 116.237 ――――――― ――――――― シェーカー最速
omasu 単純選択法 1.432 36.603 143.632 ――――――― ――――――― 単純選択法最速
omasu バブル 1.482 38.215 150.567 ――――――― ――――――― バブル最速
トーナメント法 ただいま勉強中です。
ヒープ ただいま勉強中です。
テストcsvファイル 5桁のランダム数字をソート可能なロジック キー列(1列目と2列目を連結) データ列数(26列)
作成者 ソート名称 1,000 5,000 10,000 50,000 100,000 記事
河川屋さん (PJ)クイック(改2) 0.080 0.140 0.271 0.801 1.142 クイック最速
河川屋さん (PJ)クイック(改1) 0.020 0.130 0.170 0.732 1.151 クイック最速
河川屋さん (PJ)クイック(ノーマル版) 0.130 0.160 0.210 0.831 1.192 クイック最速
マティさん (PJ)コーム 0.010 0.060 0.120 0.581 1.643 コーム最速
追伸:コームソートは何かの委員会にて1.3という最速値を決定したのでしょうか?
アクティブベーシックのみ1.4が早いのでしょうか?Cは、VBは、?
処理速度と作成時間が反比例
Posted: 2005年11月20日(日) 15:52
by omasu
お世話になります。
処理速度はどんどん速くなっておりますが、(o!o) ウルトラマンデハアリマセン
作成速度はどんどん遅くなっております。(v!v) バルタンセイジンデモアリマセン
ここをクリックすると実行速度比較が表示されます。 [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]実行環境 (ActiveBasic Ver.4.10~4.11.00)
(Cpu Pentium4 周波数2.66GHz メモリ256MByte)
テストcsvファイル 5桁のランダム数字も5桁のランダム文字もソート可能なロジック キー列(1列目と2列目を連結) データ列数(26列)
作成者 ソート名称 1,000 5,000 10,000 50,000 100,000 記事
arさん ラディックス 0.010 0.030 0.060 0.250 0.551 ラディックス最速
arさん マージ 0.010 0.060 0.120 0.411 0.892 マージ最速
arさん クイック 0.010 0.050 0.110 0.410 0.952 クイック最速
omasu マージ(arさん版) 0.030 0.160 0.380 2.123 4.527
マティさん クイック改4(800万件) 0.050 0.080 0.120 0.821 6.649
〃 〃 800万件 2080.631秒 最大件数ソート可能
イグトランスさん クイック 0.040 0.241 0.521 3.235 6.709
omasu シェル4(0.8975+0.45) 0.040 0.261 0.591 3.555 7.721 シェル最速
omasu シェル3(0.8975+¥3) 0.061 0.280 0.601 4.566 9.163
omasu コーム2(挿入法1.4) 0.091 0.391 0.822 4.767 10.705 コ-ム最速
河川屋さん コム(挿入法) 0.070 0.411 0.901 5.958 12.308
omasu シェル2(クヌース大大先生) 0.040 0.320 0.701 4.847 12.738
omasu コーム2(バブル1.4) 0.130 0.400 0.922 5.578 12.899
omasu コーム(ノーマル) 0.121 0.450 1.032 6.359 13.620
河川屋さん シェル(クヌース大先生) 0.170 0.821 2.003 13.079 30.964
omasu マージ(非再帰・非ワーク) 0.060 0.531 1.853 39.176 155.784
omasu 単純挿入法(バイナリサーチ) 0.080 0.811 2.895 65.595 261.576 単純挿入法最速
omasu シェル(選択法) 0.381 4.747 13.770 177.305 ―――――――
omasu シェル(ノーマル) 0.571 12.798 51.644 ――――――― ―――――――
omasu シェル(ノーマル・再帰) 0.661 14.801 60.006 ――――――― ―――――――
omasu 単純挿入法 0.862 18.778 77.031 ――――――― ―――――――
omasu シェーカー(バブル) 1.191 27.880 116.237 ――――――― ――――――― シェーカー最速
omasu 単純選択法 1.432 36.603 143.632 ――――――― ――――――― 単純選択法最速
omasu バブル 1.482 38.215 150.567 ――――――― ――――――― バブル最速
トーナメント法 ただいま勉強中です。
ヒープ ただいま勉強中です。
テストcsvファイル 5桁のランダム数字をソート可能なロジック キー列(1列目と2列目を連結) データ列数(26列)
作成者 ソート名称 1,000 5,000 10,000 50,000 100,000 記事
河川屋さん (PJ)クイック(改2) 0.080 0.140 0.271 0.801 1.142 クイック最速
河川屋さん (PJ)クイック(改1) 0.020 0.130 0.170 0.732 1.151 クイック最速
河川屋さん (PJ)クイック(ノーマル版) 0.130 0.160 0.210 0.831 1.192 クイック最速
マティさん (PJ)コーム 0.010 0.060 0.120 0.581 1.643 コーム最速
①.シェルソート(ノーマル) シェルソートのノーマル速度がないので作成しました。
2で割るのか、3で割るのが正規か、解りません。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Sub Sort(ByVal S As Long,ByVal E As Long)
Dim Bunkatu As Long
Bunkatu=E
Do
Bunkatu=Bunkatu\2
For i=S+Bunkatu To E Step Bunkatu
j=i
While j>=S+Bunkatu And _
lstrcmp(KeyTable[Index[j]],KeyTable[Index[j-Bunkatu]])<0
Swap(Index[j],Index[j-Bunkatu])
j=j-Bunkatu
Wend
Next i
Loop Until Bunkatu=1
End Sub
②.シェルソート(ノーマル・再帰) 初めて作った再帰処理です。
シェルを再帰で作ってもあまり意味がなかったようです。
しかし、ノーマルとは逆の作りになるとは思いませんでした。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
呼び出し方を以下のように変更してください。
コード: 全て選択
Sort(0,DataSize,0.5)
コード: 全て選択
Sub Sort(ByVal S As Long,ByVal E As Long,ByVal Bunkatu As Single)
If Bunkatu<E Then
Bunkatu=Bunkatu*2
Sort(S,E,Bunkatu)
For i=S+Bunkatu To E Step Bunkatu
j=i
While j>=S+Bunkatu And _
lstrcmp(KeyTable[Index[j]],KeyTable[Index[j-Bunkatu]])<0
Swap(Index[j],Index[j-Bunkatu])
j=j-Bunkatu
Wend
Next i
EndIf
End Sub
③.マージソート(非再帰・非ワーク) 非再帰・非ワークにチャレンジ。
1万件までは早いのに5万件を超えると急に遅くなります。
改修の必要性を感じます。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Sub Sort(ByVal S As Long,ByVal E As Long)
Dim Bunkatu As Long
Dim s As Long
Dim m As Long
Dim e As Long
Dim t As Long
Bunkatu=1
Do
Bunkatu=Bunkatu*2
For i=S To E Step Bunkatu
s=i
m=s+(Bunkatu\2)
e=s+Bunkatu
While (s<m) And (m<e) And (m<=E)
If lstrcmp(KeyTable[Index[s]],KeyTable[Index[m]])<0 Then
s=s+1
Else
t=Index[m]
For j=m To s+1 Step -1 ' ここが遅い
Index[j]=Index[j-1] ' マージではないかも
Next j
Index[s]=t
s=s+1
m=m+1
EndIf
Wend
Next i
Loop Until Bunkatu>E
End Sub
④.マージソート(arさん版) arさんのコードをソートロジック大会の実行速度比較環境に移植しました。
さすがのロジック速度には恐れ入ります。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
ワーク配列をグローバル領域に定義してください。
コード: 全て選択
Dim Work[TableSize] As Long
コード: 全て選択
Sub Sort(ByVal S As Long,ByVal E As Long)
Dim m As Long
Dim p As Long
If S<E Then
m=(S+E)\2
Sort(S,m)
Sort(m+1,E)
p=0
For i=S To m ' 申し訳ありません。
Work[p]=Index
p=p+1
Next i
i=m+1
j=0
k=S
While i<=E And j<p
If lstrcmp(KeyTable[Work[j]],KeyTable[Index])<=0 Then
Index[k]=Work[j]
j=j+1
Else
Index[k]=Index
i=i+1
End If
k=k+1
Wend
For i=j To p-1 ' 申し訳ありません。
Index[k]=Work
k=k+1
Next i
End If
End Sub
追伸:イグトランスさんのコードがいつの日か早くなっているようです。
(環境・条件・コード等、ただいま追求しています。)
Posted: 2005年11月20日(日) 21:44
by イグトランス
ところで,図書館でアルゴリズムの本を借りて読んでいたところ,
ソートの話が出てきて,クイックソートも当然出てきました。
というわけでそれを参考にして新たに作っています。
今しばらくお待ちください。
入出力は完成しましたが,肝心のソートが未だバグありで動きません。
Posted: 2005年11月22日(火) 00:27
by 河川屋
omasuさんへ
以下のシェル法プログラムは間違っています。
Sub Sort(ByVal S As Long,ByVal E As Long)
Dim Bunkatu As Long
' Bunkatu=E '間違い
Bunkatu=(E-S+1)\2 '正しい (Sの値が1以外をとってよいものとみなす。)
Do
Bunkatu=Bunkatu\2
' For i=S+Bunkatu To E Step Bunkatu '間違い(これではシェル法の本領を発揮できず、遅い。)
For i=S+Bunkatu To E '正しい
j=i
While j>=S+Bunkatu And _
lstrcmp(KeyTable[Index[j]],KeyTable[Index[j-Bunkatu]])<0
Swap(Index[j],Index[j-Bunkatu])
j=j-Bunkatu
Wend
Next i
Loop Until Bunkatu=1
End Sub
または、
Do
Bunkatu=Bunkatu\2
For k=0 To Bunkatu-1
For j=k+Bunkatu To E Step Bunkatu
と、ループのネストを1段深くする。
(こうする意味は特に無いですが、これでも可。)
こういうところを間違えると、 Bunkatuの数列をどう設定するか、など、まるで関係なくなってしまいます。
で、コムソートについての私の意見ですが、
・コムソートとバブルソートベースのシェル法は実質1行しか違わない
(下記において、 LOOP WHILE....のほうの1行が決定的な違い。)
SUB SHELL(X(),N)
IGAP=N
DO WHILE IGAP>1
IGAP=IGAP/2 'shell
' IGAP=IGAP/1.3 'comb
IMAX=N-IGAP
DO
IEX=0
FOR I=1 TO IMAX
IPULUSG=I+IGAP
IF X(I)<=X(IPULUSG) THEN
W=X(I) : X(I)=X(IPULUSG) : X(IPULUSG)=W
IEX=1
END IF
NEXT
LOOP WHILE IEX=1 'shell
' LOOP WHILE IGAP=1 AND IEX=1 'comb
LOOP
END SUB
ということまでは既に書いたよね?
つまり、IGAPに対し完全にソートしてからIGAPを小さくするのがシェル法、
ソート不完全なうちにIGAPを小さくするのがコムソート。
(だからといって、コムソートのほうが効率が悪いとも言い切れないが。)
加えて、
・初出は米国Byte誌の1991年4月号。
これは要注意であって、欧米の場合かなりマジメな雑誌でも、エイプリルフールである
場合を考えないとなんない。
つまり、作者は、何もかも承知の上でひっかけようとしている可能性のあるといういこと。
で、ひっかけでなくマジメな記事だとしても、シェル法との差が無さ過ぎるから、
NlogNの性能まではいくら何でも出そうにないです。
シェルソートの間違いについて
Posted: 2005年11月22日(火) 20:58
by omasu
お世話になります。
河川屋さんの確実なご指摘、ご指導に感謝しております。
シェルソートノーマルについて、確かに不具合がありました。
とんだ、エイプリルフールをしてしまいました。
申し訳ありません。
実行テストおよび、実行時間で気づくべきでした。
コムとシェルの違いのレッスンも理解できました。
ここをクリックすると実行速度比較が表示されます。 [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
実行環境 (ActiveBasic Ver.4.10~4.11.03)
(Cpu Pentium4 周波数2.66GHz メモリ256MByte)
テストcsvファイル 5桁のランダム数字も5桁のランダム文字もソート可能なロジック キー列(1列目と2列目を連結) データ列数(26列)
作成者 ソート名称 1,000 5,000 10,000 50,000 100,000 記事
arさん ラディックス 0.010 0.030 0.060 0.250 0.551 ラディックス最速
arさん マージ 0.010 0.060 0.120 0.411 0.892 マージ最速
arさん クイック 0.010 0.050 0.110 0.410 0.952 クイック最速
omasu マージ(arさん版) 0.030 0.160 0.380 2.123 4.527
マティさん クイック改4(800万件) 0.050 0.080 0.120 0.821 6.649
〃 〃 800万件 2080.631秒 最大件数ソート可能
イグトランスさん クイック 0.040 0.241 0.521 3.235 6.709
omasu シェル4(0.8975+0.45) 0.060 0.261 0.581 3.616 7.861 シェル最速
omasu シェル3(0.8975+¥3) 0.060 0.290 0.681 4.627 9.223
omasu コーム2(挿入法1.4) 0.091 0.391 0.822 4.767 10.705 コ-ム最速
omasu シェル2(クヌース大大先生) 0.050 0.311 0.721 4.907 11.677
河川屋さん コム(挿入法) 0.070 0.411 0.901 5.958 12.308
河川屋さん 改シェル法(クヌース大先生) 0.060 0.361 0.721 5.057 12.528
omasu コーム2(バブル1.4) 0.130 0.400 0.922 5.578 12.899
omasu シェル(ノーマル) 0.070 0.351 0.851 5.748 13.149
omasu コーム(ノーマル) 0.121 0.450 1.032 6.359 13.620
omasu 単純挿入法(バイナリサーチ) 0.080 0.811 2.895 65.595 261.576 単純挿入法最速
omasu マージ(非再帰・非ワーク) 0.060 0.531 1.853 39.176 155.784
omasu シェル(選択法) 0.381 4.747 13.770 177.305 ―――――――
omasu シェル(ノーマル・再帰) 0.661 14.801 60.006 ――――――― ―――――――
omasu 単純挿入法 0.862 18.778 77.031 ――――――― ―――――――
omasu シェーカー(バブル) 1.191 27.880 116.237 ――――――― ――――――― シェーカー最速
omasu 単純選択法 1.432 36.603 143.632 ――――――― ――――――― 単純選択法最速
omasu バブル 1.482 38.215 150.567 ――――――― ――――――― バブル最速
トーナメント法 ただいま勉強中です。
ヒープ ただいま勉強中です。
テストcsvファイル 5桁のランダム数字をソート可能なロジック キー列(1列目と2列目を連結) データ列数(26列)
作成者 ソート名称 1,000 5,000 10,000 50,000 100,000 記事
河川屋さん (PJ)クイック(改2) 0.080 0.140 0.271 0.801 1.142 クイック最速
河川屋さん (PJ)クイック(改1) 0.020 0.130 0.170 0.732 1.151 クイック最速
河川屋さん (PJ)クイック(ノーマル版) 0.130 0.160 0.210 0.831 1.192 クイック最速
マティさん (PJ)コーム 0.010 0.060 0.120 0.581 1.643 コーム最速
シェルソートのロジックの見直しを行いました。
①.シェルソート(ノーマル) 河川屋さん校正版 [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
コード: 全て選択
Sub Sort(ByVal S As Long,ByVal E As Long)
Dim Bunkatu As Long
Bunkatu=(E-S+1)\2
Do
Bunkatu=Bunkatu\2
For i=S+Bunkatu To E
j=i
While j>=S+Bunkatu And _
lstrcmp(KeyTable[Index[j]],KeyTable[Index[j-Bunkatu]])<0
Swap(Index[j],Index[j-Bunkatu])
j=j-Bunkatu
Wend
Next i
Loop Until Bunkatu=1
End Sub
②.改シェル法(クヌース大先生) 河川屋さん [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
コード: 全て選択
Sub Sort(ByVal S As Long,ByVal E As Long)
Dim Bunkatu As Long
Bunkatu=4
While Bunkatu<=E
Bunkatu=3*Bunkatu+1
Wend
While Bunkatu>1
Bunkatu=(Bunkatu-1)\3
For i=S+Bunkatu To E
j=i
While j>=S+Bunkatu And _
lstrcmp(KeyTable[Index[j]],KeyTable[Index[j-Bunkatu]])<0
Swap(Index[j],Index[j-Bunkatu])
j=j-Bunkatu
Wend
Next i
Wend
End Sub
③.シェル2(クヌース大大先生) [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
コード: 全て選択
Sub Sort(ByVal S As Long,ByVal E As Long)
Dim Bunkatu As Long
Bunkatu=4
While Bunkatu<=E
Bunkatu=3*Bunkatu+1
Wend
Do
Bunkatu=(Bunkatu-1)\3
For i=0 To Bunkatu-1 ' シェルソートをさらに分割
For j=i+Bunkatu To E Step Bunkatu
k=j
While k>=i+Bunkatu And _
lstrcmp(KeyTable[Index[k]],KeyTable[Index[k-Bunkatu]])<0
Swap(Index[k],Index[k-Bunkatu])
k=k-Bunkatu
Wend
Next j
Next i
Loop Until Bunkatu=1
End Sub
④.シェル3(0.8975+¥3) [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
コード: 全て選択
Sub Sort(ByVal S As Long,ByVal E As Long)
Dim Bunkatu As Long
Bunkatu=Int(E*0.8975) ' ギャップ初期値(件数×0.8975)
Do
Bunkatu=(Bunkatu-1)\3
If Bunkatu<4 Then ' 最後の仕上げもここでやるという手抜きです。
Bunkatu=1
EndIf
For i=0 To Bunkatu-1 ' シェルソートをさらに分割
For j=i+Bunkatu To E Step Bunkatu
k=j
While k>=i+Bunkatu And _
lstrcmp(KeyTable[Index[k]],KeyTable[Index[k-Bunkatu]])<0
Swap(Index[k],Index[k-Bunkatu])
k=k-Bunkatu
Wend
Next j
Next i
Loop Until Bunkatu=1
End Sub
⑤.シェル4(0.8975+0.45) [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
コード: 全て選択
Sub Sort(ByVal S As Long,ByVal E As Long)
Dim Bunkatu As Long
Bunkatu=Int(E*0.8975) ' ギャップ初期値(件数×0.8975)
Do
Bunkatu=Int(Bunkatu*0.45) ' クヌース大大大先生おすすめ
If Bunkatu<4 Then ' 最後の仕上げもここでやるという手抜きです。
Bunkatu=1
EndIf
For i=0 To Bunkatu-1 ' シェルソートをさらに分割
For j=i+Bunkatu To E Step Bunkatu
k=j
While k>=i+Bunkatu And _
lstrcmp(KeyTable[Index[k]],KeyTable[Index[k-Bunkatu]])<0
Swap(Index[k],Index[k-Bunkatu])
k=k-Bunkatu
Wend
Next j
Next i
Loop Until Bunkatu=1
End Sub
追伸:イグトランスさんの新ロジック、心待ちにしております!。