コード: 全て選択
#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