FreeBASIC可以很方便的调用C函数库,试着调用了快速排序qsort函数,还是有些需要注意的地方,记录一下。
一、qsort介绍(参考百度和CSDN博客)
qsort是在C函数库(stdlib.bi)里实现的快速排序函数,是根据二分法写的,其时间复杂度为n*log(n)。其函数原型为:
sub qsort (byval base as any ptr, byval num as size_t, byval nWidth as size_t, byval pCompare as function(byval as any ptr, byval as any ptr) as long)
base是待排序的数组基址,num是数组元素个数,nwidth是数组元素的大小(以字节为单位),pCompare为函数指针,指向一个自定义的比较函数,需要根据自己的需求编写。
自定义比较函数原型如下:
function 函数名 cdecl(byval a as any ptr, byval b as any ptr) as long
函数名可以随意定义,但函数中的cdecl关键字必须声明,因为是调用的C库,所以必须声明cdecl调用方式,否则出错。a和b为两个待比较的数,可以是整数、小数、字符串、结构体等,根据自己的需要进行排序,比较规则如下:
1、如果a排在b前面,则函数返回值为负整数(-1)
2、如果a和b哪个排在前面都行,则函数返回值为0
3、如果a排在b后面,则函数返回值为正整数(1)
二、示例
VFB窗体界面:
因为要使用C函数库,所以我们要引用头文件,一般在工程选项卡的特殊函数目录的FF_AppStart文件里添加。位置如图:
添加头文件:
#Include Once "crt\stdlib.bi"
#Include Once "crt\string.bi" '需要用到strcmp函数
代码如下:
#define BUFFER_SIZE 20 '定义排序数组大小
'整型数排序
function cmpInt cdecl(byval a as any ptr, byval b as any ptr) as long
Return *Cast(long ptr,a) - *Cast(long Ptr,b)
End Function
Sub Form1_Command1_BN_Clicked(hWndForm As hWnd, hWndControl As hWnd) '单击
Dim a(BUFFER_SIZE - 1) As long
Print "生成"
For i As Long = 0 To BUFFER_SIZE - 1
Randomize '随机数种子
a(i) = int(Rnd * 100000) '随机数
Print a(i),
Next
print
Print "排序"
qsort(@a(0),BUFFER_SIZE, SizeOf(long),@cmpInt)
Print "排序完成"
For i As Long = 0 To BUFFER_SIZE - 1
Print a(i),
Next
print
End Sub
'浮点型排序
function cmpDbl cdecl(byval a as any ptr, byval b as any ptr) as long
Dim c As Double Ptr = Cast(Double Ptr, a) '需要先转换类型保存
Dim d As Double Ptr = Cast(Double Ptr, b)
return IIf(*c > *d,1,-1) '比较
End Function
Sub Form1_Command2_BN_Clicked(hWndForm As hWnd, hWndControl As hWnd) '单击
Dim a(BUFFER_SIZE - 1) As Double
Print "生成"
For i As Long = 0 To BUFFER_SIZE - 1
Randomize '随机数种子
a(i) = Rnd * 100000 '随机数
Print a(i),
Next
print
Print "排序"
qsort(@a(0),BUFFER_SIZE, SizeOf(Double),@cmpDbl)
Print "排序完成"
For i As Long = 0 To BUFFER_SIZE - 1
Print a(i),
Next
print
End Sub
'字符串排序
function cmpStr cdecl(byval a as any ptr, byval b as any ptr) as long
Dim c As ZString Ptr = Cast(ZString Ptr, a)
Dim d As ZString Ptr = Cast(ZString Ptr, b)
return strcmp(c,d)
End Function
Sub Form1_Command3_BN_Clicked(hWndForm As hWnd, hWndControl As hWnd) '单击
Dim s As String = "0123456789"
Dim a(BUFFER_SIZE - 1) As ZString * 10 '字符串使用ZString比较方便用于C函数库的排序
Print "生成"
For i As Long = 0 To BUFFER_SIZE - 1
For j As Long = 0 To 5
Randomize '随机数种子
a(i) &= Mid(s,int(Rnd * 10) + 1,1) '随机数
Next j
Print a(i),
Next
print
Print "排序"
qsort(@a(0),BUFFER_SIZE, SizeOf(ZString * 10),@cmpStr)
Print "排序完成"
For i As Long = 0 To BUFFER_SIZE - 1
Print a(i),
Next
print
End Sub
'结构体排序
Type Student '学生结构
ID As Long '学号
Name As String '名字
Score As Long '分数
End Type
function cmpType cdecl(byval a as any ptr, byval b as any ptr) as long
Dim c As Student Ptr = Cast(Student Ptr, a)
Dim d As Student Ptr = Cast(Student Ptr, b)
Return c->Score - d->Score '用分数排名 从小到大
End Function
Sub Form1_Command4_BN_Clicked(hWndForm As hWnd, hWndControl As hWnd) '单击
Dim a(BUFFER_SIZE - 1) As Student
Print "生成"
For i As Long = 0 To BUFFER_SIZE - 1
Randomize '随机数种子
a(i).ID = int(Rnd * 10000) '随机数
a(i).Name = "张三" & i & "号"
Randomize '随机数种子
a(i).Score = Int(Rnd * 120 + 1)
Print a(i).ID,a(i).Name,a(i).Score
Next
print
Print "排序"
qsort(@a(0),BUFFER_SIZE, SizeOf(Student),@cmpType)
Print "排序完成"
For i As Long = 0 To BUFFER_SIZE - 1
Print a(i).ID,a(i).Name,a(i).Score
Next
print
End Sub
运行效果:
整型数:
浮点型:
字符串:(为了方便看出来,使用的是数字字符串)
结构体:
完整代码:
https://github.com/rainheart311/VisualFreeBASIC/tree/master/qsort