elem2 as temployee, _
unused1 as long, _
unused2 as long) as integer
dim ret as integer
ret = sgn(elem1.salary - elem2.salary)
if ret = 0 then
ret = strcomp(elem1.name, elem2.name, vbtextcompare)
end if
comparesalaryname = ret
end function
'先按姓名比较,再按薪水比较
function comparenamesalary(elem1 as temployee, _
elem2 as temployee, _
unused1 as long, _
unused2 as long) as integer
dim ret as integer
ret = strcomp(elem1.name, elem2.name, vbtextcompare)
if ret = 0 then
ret = sgn(elem1.salary - elem2.salary)
end if
comparenamesalary = ret
end function
最后再看看我们来看看我们最终的qsort的声明。
sub qsort(byval arrayptr as long, byval ncount as long, _
byval nelemsize as integer, byval pfncompare as long)
上面的arrayptr是需要排序数组的第一个元素的指针,ncount是数组的元素个数,nelemsize是每个元素大小,pfncompare就是我们的比较函数指针。这个声明和c库函数里的qsort是极为相似的。
和c一样,我们完全可以将basic的函数指针传递给basic的qsort函数。
使用方式如下:
dim employees(1 to 10000) as temployee
'假设下面的调用对employees数组进行了赋值初始化。
call initarray()
'现在就可以调用我们的qsort来进行排序了。
call qsort(varptr(employees(1)), ubound(employees), _
lenb(employees(1)), addressof comparesalaryname)
'或者先按姓名排,再按薪水排
call qsort(varptr(employees(1)), ubound(employees), _
lenb(employees(1)), addressof comparenamesalary)
聪明的朋友们,你们是不是已经看出这里的奥妙了呢?作为一个测验,你能现在就给出在qsort里使用函数指针的方法吗?比如现在我们要通过调用函数指针来比较数组的第i个元素和第j个元素的大小。
没错,当然要使用前面声明的compare(其实就是callwindowproc)这个api来进行强制回调。
具体的实现如下:
sub qsort(byval arrayptr as long, byval ncount as long, _
byval nelemsize as integer, byval pfncompare as long)
dim i as long, j as long
'这里省略快速排序算法的具体实现,仅给出比较两个元素的方法。
if compare(pfncompare, arrayptr + (i - 1) * nelemsize, _
arrayptr + (j - 1) * nelemsize, 0, 0) > 0 then
'如果第i个元素比第j个元素大则用copymemory来交换这两个元素。
end if