ページ 6 / 8
クイックソート(入門編)について
Posted: 2005年11月24日(木) 21:41
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
omasu クイック(入門編) 0.040 0.210 0.450 2.834 6.639
マティさん クイック改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 P As Long
If S<E Then
Swap(Index[S],Index[(S+E)\2])
P=S
For i=S+1 To E
If lstrcmp(KeyTable[Index],KeyTable[Index[S]])<0 Then
P=P+1
Swap(Index[P],Index)
EndIf
Next i
Swap(Index[S],Index[P])
Sort(P+1,E)
Sort(S,P-1)
EndIf
End Sub
しかし、最悪のデータの並びの存在、スタックオーバーフロー対策等、
何も考えていないため、今後の課題としたいと思います。
Posted: 2005年11月24日(木) 22:11
by マティ
ネットで検索すると
omasuさんが投稿したようなコードが上位でヒットします。
このコードを使用した結果
クイックソートって、動作が不安定だなって思っていました。
(だから不安定ソートって勘違いしたくらいです。)
このアルゴリズムでは、件数が多くなるとスタックオーバーを引き起こします。
また、元データが逆順の場合に性能が最悪になります。
初心者向けにも
河川屋さんが投稿したロジックを元に移植する事を推奨します。
http://www.discoversoft.net/forum/viewt ... c&start=16
omasuさん、これからも頑張って下さい。
PS.ActiveBasicは、
Subや
Functionを使用しない方が早いようです。
アニバーサリー
Posted: 2005年11月24日(木) 22:56
by omasu
マティさんへ
ありがとうございます。
ごさっしのとおり(m!m)
ネットで探しまわり、直感で一番解りやすいロジックを参考にABに模倣移植しました。
参考文献はC言語が圧倒的に多く、VBが続き、ABでは皆無です。
クイック=難しい、ABで私のような初心者には理解しやすいと感じ投稿しました。
追伸:arさんのマージソートは実行比較環境に何とか移植できました、
arさんのクイックソートは、私の手には負えません。
どなたか!・・・
追伸:今、ヒープを登頂中です。難しすぎます。
Posted: 2005年11月24日(木) 23:18
by イグトランス
河川屋さんのコードのコメントを読み返してみましたが,結局辿り着くところは同じようで,
私が読んでいる本に書いてあることと同じことを実践されています。(改3まで)
それでもやる気をなくしたわけではありませんから,やるだけやりますよ。
(最近プログラミングに割ける時間が少なくて←言い訳)
Posted: 2005年11月24日(木) 23:22
by マティ
omasuさん以下のロジックで動作するでしょうか?
QuickSortをomasuさん風に書くと [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
コード: 全て選択
Sub QuickSort( S As Long, E As Long)
Dim L As Long '左から
Dim R As Long '右から
Dim K As Long '基準
'
If S<E Then
L=S : R=E: K=Index[(S+E)\2]
Do
While lstrcmp(KeyTable[Index[L]],KeyTable[K])<0: L=L+1: Wend
While lstrcmp(KeyTable[Index[R]],KeyTable[K])>0: R=R-1: Wend
If (L <= R) Then
Swap(Index[L],Index[R])
L=L+1 : R=R-1
End If
Loop Until (L > R)
QuickSort(S, R) '左側を再処理
QuickSort(L, E) '右側を再処理
End If
End Sub
初心者向けに、分かりやすくしたつもりです。
アニバーサリーⅡ
Posted: 2005年11月24日(木) 23:54
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
omasu クイック(入門編) 0.040 0.210 0.450 2.834 6.639
マティさん クイック改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
マティさん クイック(初級編) 0.040 0.250 0.510 3.275 7.200
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 コーム最速
両方から攻める方法は少し難しいです。
クイックソート
Posted: 2005年11月26日(土) 17:59
by イグトランス
とりあえず形になったので投稿します。
単に数値化するだけでも随分と早くなるだろうと企んだわけですが,
思惑は外れ大して早くなりませんでした。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします] ちなみにDWordPtr2は現在のAB 4.11.03でポインタへのポインタ型が扱えないことに対する苦肉の策です。
コード: 全て選択
#strict
#prompt
Declare Function timeGetTime Lib "winmm.dll" () As DWord
Declare Function timeBeginPeriod Lib "winmm.dll" (ByVal uPeriod As DWord) As Long
Declare Function timeEndPeriod Lib "winmm.dll" (ByVal uPeriod As DWord) As Long
Declare Function StrChr Lib "shlwapi" Alias "StrChrA" (psz As *Char, ch As Char) As *Char
Declare Function StrToInt Lib "shlwapi" Alias "StrToIntA" (psz As *Char) As Long
Const Width = 26
Const Key = 1
Dim Path As String, Temp As String, InFile As String, OutFile As String
#define MAINPC
#ifdef MAINPC
Path = "h:\"
#else
Path = "c:\temp\"
#endif
Function ReadFromFile(pszFileName As *Char) As *DWord
ReadFromFile = 0
Dim hFile As HANDLE, hMap As HANDLE
hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, ByVal 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0) As HANDLE
If hFile = INVALID_HANDLE_VALUE Then
Exit Function
End If
Dim pBuffer As *Char
Dim Size As DWord, ReadSize As DWord
Size = GetFileSize(hFile, 0)
pBuffer = calloc(Size + 1)
ReadFile(hFile, pBuffer, Size, VarPtr(ReadSize), ByVal 0)
CloseHandle(hFile)
ReadFromFile = LoadData(pBuffer)
free(pBuffer)
End Function
Function LoadData(pBuffer As *Char) As *DWord
Dim pData As *DWord
pData = malloc(NumOfRecord * Width * SizeOf (DWord))
Dim i As Long
For i = 0 To ELM(NumOfRecord)
If GetByte(pBuffer) = 0 Then
Exit For
End If
Dim j As Long
For j = 0 To ELM(Width)
pData[i * Width + j] = StrToInt(pBuffer)
Dim p As *Char
p = StrChr(pBuffer, &h2c) 'Asc(",")
If p = 0 Then
Exit For
End If
pBuffer = p + 1
Next
Dim pNextLine As *Char
pNextLine = StrChr(pBuffer, Asc(Ex"\n"))
If pNextLine = 0 Then
Exit For
End If
pBuffer = pNextLine + 1
Next
LoadData = pData
End Function
Sub WriteToFile(DataIndex As *DWordPtr2, FileName As *Char)
Dim hOut As HANDLE
hOut = CreateFile(FileName, GENERIC_WRITE, 0, ByVal 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
If hOut = INVALID_HANDLE_VALUE Then
Dim strMsg As String
strMsg = MakeStr(FileName) + "を開けませんでした。"
MessageBox(0, strMsg, 0, MB_ICONERROR)
End'Exit Sub
End If
Dim i As Long
For i = 0 To ELM(NumOfRecord)
Dim p As *DWord
p = DataIndex As *DWord
Dim str As String
str = ""
Dim j As Long
For j = 0 To ELM(Width)
str = str + Str$(p[j]) + ","
Next
str = str + Ex"\r\n"
Dim WrittenBytes As DWord
WriteFile(hOut, StrPtr(str), Len(str), VarPtr(WrittenBytes), ByVal 0)
Next
CloseHandle(hOut)
End Sub
Const Period = 1
Sub Sort(Index As *DWordPtr2, Num As DWord)
timeBeginPeriod(Period)
Dim Time As DWord
Time = timeGetTime()
QuickSort5(Index, Num)
Time = timeGetTime() - Time
timeEndPeriod(Period)
Print "ソート所要時間", Time As Double / 1000, "秒"
End Sub
TypeDef DWordPtr2 = DWord
' ↓ ここからプログラムが実行されます
Dim NumOfRecord As DWord
#ifdef _DEBUG
NumOfRecord = 2000
#else
Print "件数を指定してください。"
Input NumOfRecord
If NumOfRecord = 0 Then
End
End If
#endif
Temp = Str$(NumOfRecord) + ".csv"
InFile = Path + "infile" + Temp
OutFile = Path + "outfile" + Temp
Dim pRecord As *DWord
pRecord = ReadFromFile(InFile)
If pRecord = 0 Then
End
End If
Const RowsNum = 3
Dim KeyRows[RowsNum] = [1, 2, 3, 4] As DWord
Dim Index As *DWordPtr2
Index = malloc(NumOfRecord * SizeOf (DWordPtr2))
Dim i As DWord
For i = 0 To ELM(NumOfRecord)
Index = VarPtr(pRecord[i * Width]) As DWordPtr2
Next
Sort(Index, ELM(NumOfRecord))
WriteToFile(Index, StrPtr(OutFile))
free(pRecord)
free(Index)
コード: 全て選択
Const GetAt(a) = GetDWord(a + (Key << 2)) ' << 2はSizeOf (DWord)をかける代わり
Const Limit = 8
Sub QuickSort5(pIndex As *DWordPtr2, Size As DWord)
Dim Stack[ELM(64)] As DWord, pos As DWord
Dim Left As Long, Right As Long
Left = 0
Right = Size
Do
While Right > Left + Limit
' 左端,中央,右端から中央値を選び,それを分割の基準にする。
Dim Center As DWord, Temp As DWordPtr2
Center = (Left + Right) >> 1 ' >> 1は2で割る代わり
If GetAt(pIndex[Left]) > GetAt(pIndex[Center]) Then
Temp = pIndex[Left] : pIndex[Left] = pIndex[Center] : Index[Center] = Temp
End If
If GetAt(pIndex[Left]) > GetAt(pIndex[Right]) Then
Temp = pIndex[Left] : pIndex[Left] = pIndex[Right] : Index[Right] = Temp
End If
If GetAt(pIndex[Center]) > GetAt(pIndex[Right]) Then
Temp = pIndex[Center] : pIndex[Center] = pIndex[Right] : Index[Right] = Temp
End If
' 分割
Dim v As *DWord, i As DWord, j As DWord
v = pIndex[Center] As *DWord
Temp = v As DWordPtr2 : pIndex[Center] = pIndex[Right - 1] : Index[Right - 1] = Temp
i = Left + 1
j = Right - 2
Do
While GetAt(pIndex) < GetAt(v)
i = i + 1
Wend
While GetAt(pIndex[j]) > GetAt(v)
j = j - 1
Wend
If i > j Then Exit Do
Temp = pIndex : pIndex = pIndex[j] : Index[j] = Temp
i = i + 1
j = j - 1
Loop
/*
If pos >= 63 Then
Print "Stack Overflow"
Exit Sub
End If
'*/
If i - Left > Right - i Then
Stack[pos] = Left : pos = pos + 1
Stack[pos] = j : pos = pos + 1
Left = i + 1
Else
Stack[pos] = Left + 1 : pos = pos + 1
Stack[pos] = Right : pos = pos + 1
Right = j
End If
Wend
If pos < 2 Then Exit Do
pos = pos - 1 : Right = Stack[pos]
pos = pos - 1 : Left = Stack[pos]
Loop
InsertionSort3(pIndex, Size)
End Sub
Sub InsertionSort3(pIndex As *DWordPtr2, Size As DWord)
Dim i As Long
For i = 1 To Size
Dim v As DWordPtr2
v = pIndex
Dim j As DWord
j = i
While j > 0
If Not GetAt(pIndex[j - 1]) > GetAt(v) Then
Exit While
End If
pIndex[j] = pIndex[j - 1]
j = j - 1
Wend
pIndex[j] = v
Next
End Sub
クイックソート5、挿入ソート3について
Posted: 2005年11月26日(土) 18:27
by omasu
イグトランスさんへ(皆さんへ)
ありがとうございます。
クイックソート5 !!!!!m(_ _)m!!!!!
挿入ソート3 !!!m(_ _)m!!!
覚悟を決め、実行してみます。
非常に高度なため、とりあえずでは動かせそうもないですが、
コピー、ペースト、実行 ※とりあえずではいきなり終了します。
(ところどころで設定すべき箇所があると思われます。)
自己流クイック(中級編?)
Posted: 2005年11月26日(土) 21:00
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
omasu クイック(中級編?) 0.040 0.230 0.460 2.614 6.029
omasu クイック(入門編) 0.040 0.210 0.450 2.834 6.639
マティさん クイック改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
マティさん クイック(初級編) 0.040 0.250 0.510 3.275 7.200
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)
If E-S>9 Then ' 10(9)件まで砕いたら挿入ソートへ移行
Dim P As Long
P=(S+E)\2
If lstrcmp(KeyTable[Index[P]],KeyTable[Index[E]])>0 Then ' 最悪のパターンを減らすため
Swap(Index[P],Index[E]) ' 先頭と中央と最後をソート
EndIf
If lstrcmp(KeyTable[Index[S]],KeyTable[Index[P]])>0 Then
Swap(Index[S],Index[P])
EndIf
Swap(Index[S],Index[P]) ' ソートした中央値を基準値とする
P=S
For i=S+1 To E
If lstrcmp(KeyTable[Index],KeyTable[Index[S]])<0 Then
P=P+1
Swap(Index[P],Index)
EndIf
Next i
Swap(Index[S],Index[P])
If (E-(P+1))<((P-1)-S) Then ' 件数が小さい方から再帰処理
Sort(P+1,E)
Sort(S,P-1)
Else
Sort(S,P-1)
Sort(P+1,E)
EndIf
Else
InsertionSort(S,E) ' 単純挿入ソート
EndIf
End Sub
Sub InsertionSort(ByVal S As Long,ByVal E As Long)
For i=S+1 To E
j=i
While j>=S+1 And _
lstrcmp(KeyTable[Index[j]],KeyTable[Index[j-1]])<0
Swap(Index[j],Index[j-1])
j=j-1
Wend
Next i
End Sub
①最悪のデータ配列に対応
先頭と中央と最後のデータの3件の内、中央値を基準値とする
②スタックオーバーフローに対応
再帰処理は件数の小さい方から実行する
③速度向上に対応
ある程度細かくなったら単純挿入ソートに移行する
※10(9)件は3件~30件までのテストにより最高値を採用
追伸:投稿後にバグに気づきバグつぶしをしてしまいました。
冷や汗が出ました。
Posted: 2005年11月26日(土) 23:57
by イグトランス
すみませんでした。
以下の部分を消して,infileXXX.csvのあるフォルダへのパスを変数Pathへ代入してください。
コード: 全て選択
#define MAINPC
#ifdef MAINPC
Path = "h:\"
#else
Path = "c:\temp\"
#endif
ところで今回のはデータを全て数値(DWord)へ変換しています。
なので数字しか扱えないので「5桁のランダム数字」に分類してください。
しかし申し訳ありません,2列目だけをキーとして扱っていました。
1列目と2列目をキーとしなければならないのですよね。
今度修正してきます。
Posted: 2005年11月27日(日) 08:29
by マティ
omasuさん先頭と中央と最後をソートし中央値を基準値とする処理ですが、Sが最大となる場合に、Sが基準値となっています。確認してください。
omasuさんのコード
コード: 全て選択
P=(S+E)\2
If lstrcmp(KeyTable[Index[P]],KeyTable[Index[E]])>0 Then ' 最悪のパターンを減らすため
Swap(Index[P],Index[E]) ' 先頭と中央と最後をソート
EndIf
If lstrcmp(KeyTable[Index[S]],KeyTable[Index[P]])>0 Then
Swap(Index[S],Index[P])
EndIf
Swap(Index[S],Index[P]) ' ソートした中央値を基準値とする
P=S
これだとちゃんと基準を取れると思います。置き換えてみて下さい。
コード: 全て選択
P=(S+E)\2
' 最悪のパターンを減らすため、先頭と中央と最後をソート
If lstrcmp(KeyTable[Index[S]],KeyTable[Index[P]])>0 Then
Swap(Index[S],Index[P])
EndIf
If lstrcmp(KeyTable[Index[P]],KeyTable[Index[E]])>0 Then
Swap(Index[P],Index[E])
If lstrcmp(KeyTable[Index[S]],KeyTable[Index[P]])>0 Then
Swap(Index[S],Index[P])
EndIf
EndIf
' Pに中央値が入っています。
コーディングミスについて
Posted: 2005年11月27日(日) 09:11
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
omasu クイック(中級編) 0.050 0.190 0.421 2.493 5.398
omasu クイック(入門編) 0.040 0.210 0.450 2.834 6.639
マティさん クイック改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
マティさん クイック(初級編) 0.040 0.250 0.510 3.275 7.200
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)
If E-S>9 Then ' 10(9)件まで砕いたら挿入ソートへ移行
Dim P As Long
P=(S+E)\2
If lstrcmp(KeyTable[Index[S]],KeyTable[Index[P]])>0 Then ' 最悪のパターンを減らすため、先頭と中央と最後をソート
Swap(Index[S],Index[P])
EndIf
If lstrcmp(KeyTable[Index[P]],KeyTable[Index[E]])>0 Then
Swap(Index[P],Index[E])
If lstrcmp(KeyTable[Index[S]],KeyTable[Index[P]])>0 Then
Swap(Index[S],Index[P])
EndIf
EndIf ' Pに中央値が入っています。
Swap(Index[S],Index[P]) ' ソートした中央値を基準値とする
P=S
For i=S+1 To E
If lstrcmp(KeyTable[Index],KeyTable[Index[S]])<0 Then
P=P+1
Swap(Index[P],Index)
EndIf
Next i
Swap(Index[S],Index[P])
If (E-(P+1))<((P-1)-S) Then ' 件数が小さい方から再帰処理
Sort(P+1,E)
Sort(S,P-1)
Else
Sort(S,P-1)
Sort(P+1,E)
EndIf
Else
InsertionSort(S,E) ' 単純挿入ソート
EndIf
End Sub
Sub InsertionSort(ByVal S As Long,ByVal E As Long)
For i=S+1 To E
j=i
While j>=S+1 And _
lstrcmp(KeyTable[Index[j]],KeyTable[Index[j-1]])<0
Swap(Index[j],Index[j-1])
j=j-1
Wend
Next i
End Sub
追伸:皆様の上級編に近づけるようがんばります。
クイックソート5、挿入ソート3について
Posted: 2005年11月27日(日) 13:22
by omasu
お世話になります。
イグトランスさんのクイックソートが動きました。
しかし、私の動かし方が悪いのか、
入力ファイル 千件の出力件数は 864件・・・ソートはされています。
〃 一万件 〃 1794件・・・ソートはされています。
〃 十万件 〃 4369件・・・ソートはされています。
また、例の私の環境のメモリ256MBの影響かもしれません。
ちなみの 千件のソートは0秒
十万件 6.578秒です?????
スタック数とかメモリ制限とか、いろいろ調べる必要があるやもしれません。
Posted: 2005年11月27日(日) 21:45
by イグトランス
それは単に私のバグに違いありません。
#クイックソート1つ書けないでどうするんだ,俺。
コーヒーブレイク
Posted: 2005年11月28日(月) 21:06
by omasu
お世話になります。
ちょっと休憩します。
私の年はいくつだと思いますか?