[Fortran] 纯文本查看 复制代码
Module QuickSortMod
!
! quick sort algorithm
!
Integer, Parameter :: RealPrec = kind(0.0d0)
!
! InterFace
!
Interface QuickSort
Module Procedure quick_sort_i
Module Procedure quick_sort_d
End InterFace QuickSort
Contains
!****************************************************************!******************************************************************************!
Recursive Subroutine quick_sort_i(ilist1,ilist2,dlist1,zlist1)
Integer, dimension(:), intent(in out) :: ilist1
Integer, dimension(:), intent(in out), optional :: ilist2
Real(RealPrec), dimension(:), intent(in out), optional :: dlist1
Complex(RealPrec), dimension(:), intent(in out), optional :: zlist1
Integer :: i, j, n
Integer :: chosen, temp
complex(RealPrec) :: ztemp
Integer, parameter :: max_simple_sort_size = 6
n = size(ilist1)
If (n <= max_simple_sort_size) Then
! Use interchange sort for small lists
If ( (Present(ilist2)) .and. (Present(dlist1)) .and. (Present(zlist1)) ) Then
call interchange_sort(ilist1,ilist2=ilist2,dlist1=dlist1,zlist1=zlist1)
ElseIf ( (Present(dlist1)) .and. (Present(zlist1)) ) Then
call interchange_sort(ilist1,dlist1=dlist1,zlist1=zlist1)
ElseIf ( (Present(ilist2)) .and. (Present(dlist1)) ) Then
call interchange_sort(ilist1,ilist2=ilist2,dlist1=dlist1)
ElseIf ( (Present(ilist2)) .and. (Present(zlist1)) ) Then
call interchange_sort(ilist1,ilist2=ilist2,zlist1=zlist1)
ElseIf ( (Present(dlist1)) ) Then
call interchange_sort(ilist1,dlist1=dlist1)
ElseIf ( (Present(ilist2)) ) Then
call interchange_sort(ilist1,ilist2=ilist2)
ElseIf ( (Present(zlist1)) ) Then
call interchange_sort(ilist1,zlist1=zlist1)
Else
call interchange_sort(ilist1)
endif
Else
! Use partition (“quick”) sort
chosen = ilist1(n/2)
i = 0
j = n + 1
Do
! Scan list from left End
! until element >= chosen is found
Do
i = i + 1
If (ilist1(i) >= chosen) exit
End Do
! Scan list from right End
! until element <= chosen is found
Do
j = j - 1
If (ilist1(j) <= chosen) exit
End Do
If (i < j) Then
! Swap two out of place elements
temp = ilist1(i)
ilist1(i) = ilist1(j)
ilist1(j) = temp
If (Present(ilist2)) Then
temp = ilist2(i)
ilist2(i) = ilist2(j)
ilist2(j) = temp
endif
If (Present(dlist1)) Then
ztemp = dlist1(i)
dlist1(i) = dlist1(j)
dlist1(j) = ztemp
endif
If (Present(zlist1)) Then
ztemp = zlist1(i)
zlist1(i) = zlist1(j)
zlist1(j) = ztemp
endif
Else If (i == j) Then
i = i + 1
exit
Else
exit
End If
End Do
If ( (Present(ilist2)) .and. (Present(dlist1)) .and. (Present(zlist1)) ) Then
If (1 < j) call quick_sort_i(ilist1(:j),ilist2=ilist2(:j),dlist1=dlist1(:j),zlist1=zlist1(:j))
If (i < n) call quick_sort_i(ilist1(i:),ilist2=ilist2(i:),dlist1=dlist1(i:),zlist1=zlist1(i:))
ElseIf ( (Present(dlist1)) .and. (Present(zlist1)) ) Then
If (1 < j) call quick_sort_i(ilist1(:j),dlist1=dlist1(:j),zlist1=zlist1(:j))
If (i < n) call quick_sort_i(ilist1(i:),dlist1=dlist1(i:),zlist1=zlist1(i:))
ElseIf ( (Present(ilist2)) .and. (Present(dlist1)) ) Then
If (1 < j) call quick_sort_i(ilist1(:j),ilist2=ilist2(:j),dlist1=dlist1(:j))
If (i < n) call quick_sort_i(ilist1(i:),ilist2=ilist2(i:),dlist1=dlist1(i:))
ElseIf ( (Present(ilist2)) .and. (Present(zlist1)) ) Then
If (1 < j) call quick_sort_i(ilist1(:j),ilist2=ilist2(:j),zlist1=zlist1(:j))
If (i < n) call quick_sort_i(ilist1(i:),ilist2=ilist2(i:),zlist1=zlist1(i:))
ElseIf ( (Present(dlist1)) ) Then
If (1 < j) call quick_sort_i(ilist1(:j),dlist1=dlist1(:j))
If (i < n) call quick_sort_i(ilist1(i:),dlist1=dlist1(i:))
ElseIf ( (Present(ilist2)) ) Then
If (1 < j) call quick_sort_i(ilist1(:j),ilist2=ilist2(:j))
If (i < n) call quick_sort_i(ilist1(i:),ilist2=ilist2(i:))
ElseIf ( (Present(zlist1)) ) Then
If (1 < j) call quick_sort_i(ilist1(:j),zlist1=zlist1(:j))
If (i < n) call quick_sort_i(ilist1(i:),zlist1=zlist1(i:))
Else
If (1 < j) call quick_sort_i(ilist1(:j))
If (i < n) call quick_sort_i(ilist1(i:))
endif
End If ! test for small array
End Subroutine quick_sort_i
!****************************************************************!******************************************************************************!
Subroutine interchange_sort(ilist1,ilist2,dlist1,zlist1)
Integer, dimension(:), intent(in out) :: ilist1
Integer, dimension(:), intent(in out), optional :: ilist2
Real(RealPrec), dimension(:), intent(in out), optional :: dlist1
Complex(RealPrec), dimension(:), intent(in out), optional :: zlist1
Integer :: i, j
Integer :: temp
complex(RealPrec) :: ztemp
Do i = 1, size(ilist1) - 1
Do j = i + 1, size(ilist1)
If (ilist1(i) > ilist1(j)) Then
temp = ilist1(i)
ilist1(i) = ilist1(j)
ilist1(j) = temp
If (Present(ilist2)) Then
temp = ilist2(i)
ilist2(i) = ilist2(j)
ilist2(j) = temp
endif
If (Present(dlist1)) Then
ztemp = dlist1(i)
dlist1(i) = dlist1(j)
dlist1(j) = ztemp
endif
If (Present(zlist1)) Then
ztemp = zlist1(i)
zlist1(i) = zlist1(j)
zlist1(j) = ztemp
endif
End If
End Do
End Do
End Subroutine interchange_sort
!****************************************************************!******************************************************************************!
Recursive Subroutine quick_sort_d(dlist1,dlist2,ilist1,zlist1)
Real(RealPrec), dimension(:), intent(in out) :: dlist1
Real(RealPrec), dimension(:), intent(in out), optional :: dlist2
Integer, dimension(:), intent(in out), optional :: ilist1
Complex(RealPrec), dimension(:), intent(in out), optional :: zlist1
Integer :: i, j, n
Integer :: temp
real(RealPrec) :: dtemp, chosen
Complex(RealPrec) :: ztemp
Integer, parameter :: max_simple_sort_size = 6
n = size(dlist1)
If (n <= max_simple_sort_size) Then
! Use interchange sort for small lists
If ( (Present(ilist1)).and.(Present(dlist2)) .and. (Present(zlist1)) ) Then
call interchange_sort_d(dlist1,dlist2=dlist2,ilist1=ilist1,zlist1=zlist1)
ElseIf( (Present(ilist1)) .and. (Present(zlist1)) ) Then
call interchange_sort_d(dlist1,ilist1=ilist1,zlist1=zlist1)
ElseIf ( (Present(dlist2)) .and. (Present(zlist1)) ) Then
call interchange_sort_d(dlist1,dlist2=dlist2,zlist1=zlist1)
ElseIf ( (Present(dlist2)) .and. (Present(ilist1)) ) Then
call interchange_sort_d(dlist1,dlist2=dlist2,ilist1=ilist1)
ElseIf ( (Present(ilist1)) ) Then
call interchange_sort_d(dlist1,ilist1=ilist1)
ElseIf ( (Present(zlist1)) ) Then
call interchange_sort_d(dlist1,zlist1=zlist1)
ElseIf ( (Present(dlist2)) ) Then
call interchange_sort_d(dlist1,dlist2=dlist2)
Else
call interchange_sort_d(dlist1)
endif
Else
! Use partition (“quick”) sort
chosen = dlist1(n/2)
i = 0
j = n + 1
Do
! Scan list from left End
! until element >= chosen is found
Do
i = i + 1
If (dlist1(i) >= chosen) exit
End Do
! Scan list from right End
! until element <= chosen is found
Do
j = j - 1
If (dlist1(j) <= chosen) exit
End Do
If (i < j) Then
! Swap two out of place elements
dtemp = dlist1(i)
dlist1(i) = dlist1(j)
dlist1(j) = dtemp
If (Present(ilist1)) Then
temp = ilist1(i)
ilist1(i) = ilist1(j)
ilist1(j) = temp
endif
If (Present(dlist2)) Then
dtemp = dlist2(i)
dlist2(i) = dlist2(j)
dlist2(j) = dtemp
endif
If (Present(zlist1)) Then
ztemp = zlist1(i)
zlist1(i) = zlist1(j)
zlist1(j) = ztemp
endif
Else If (i == j) Then
i = i + 1
exit
Else
exit
End If
End Do
If ( (Present(ilist1)).and.(Present(dlist2)) .and. (Present(zlist1)) ) Then
If (1 < j) call quick_sort_d(dlist1(:j),dlist2=dlist2(:j),ilist1=ilist1(:j),zlist1=zlist1(:j))
If (i < n) call quick_sort_d(dlist1(i:),dlist2=dlist2(i:),ilist1=ilist1(i:),zlist1=zlist1(i:))
ElseIf( (Present(ilist1)) .and. (Present(zlist1)) ) Then
If (1 < j) call quick_sort_d(dlist1(:j),ilist1=ilist1(:j),zlist1=zlist1(:j))
If (i < n) call quick_sort_d(dlist1(i:),ilist1=ilist1(i:),zlist1=zlist1(i:))
ElseIf ( (Present(dlist2)) .and. (Present(zlist1)) ) Then
If (1 < j) call quick_sort_d(dlist1(:j),dlist2=dlist2(:j),zlist1=zlist1(:j))
If (i < n) call quick_sort_d(dlist1(i:),dlist2=dlist2(i:),zlist1=zlist1(i:))
ElseIf ( (Present(dlist2)) .and. (Present(ilist1)) ) Then
If (1 < j) call quick_sort_d(dlist1(:j),dlist2=dlist2(:j),ilist1=ilist1(:j))
If (i < n) call quick_sort_d(dlist1(i:),dlist2=dlist2(i:),ilist1=ilist1(i:))
ElseIf ( (Present(ilist1)) ) Then
If (1 < j) call quick_sort_d(dlist1(:j),ilist1=ilist1(:j))
If (i < n) call quick_sort_d(dlist1(i:),ilist1=ilist1(i:))
ElseIf ( (Present(zlist1)) ) Then
If (1 < j) call quick_sort_d(dlist1(:j),zlist1=zlist1(:j))
If (i < n) call quick_sort_d(dlist1(i:),zlist1=zlist1(i:))
ElseIf ( (Present(dlist2)) ) Then
If (1 < j) call quick_sort_d(dlist1(:j),dlist2=dlist2(:j))
If (i < n) call quick_sort_d(dlist1(i:),dlist2=dlist2(i:))
Else
If (1 < j) call quick_sort_d(dlist1(:j))
If (i < n) call quick_sort_d(dlist1(i:))
endif
End If ! test for small array
End Subroutine quick_sort_d
!****************************************************************!******************************************************************************!
Subroutine interchange_sort_d(dlist1,dlist2,ilist1,zlist1)
Real(RealPrec), dimension(:), intent(in out) :: dlist1
Real(RealPrec), dimension(:), intent(in out), optional :: dlist2
Integer, dimension(:), intent(in out), optional :: ilist1
Complex(RealPrec), dimension(:), intent(in out), optional :: zlist1
Integer :: i, j
Integer :: temp
real(RealPrec) :: dtemp
complex(RealPrec) :: ztemp
Do i = 1, size(dlist1) - 1
Do j = i + 1, size(dlist1)
If (dlist1(i) > dlist1(j)) Then
dtemp = dlist1(i)
dlist1(i) = dlist1(j)
dlist1(j) = dtemp
If (Present(dlist2)) Then
dtemp = dlist2(i)
dlist2(i) = dlist2(j)
dlist2(j) = dtemp
endif
If (Present(ilist1)) Then
temp = ilist1(i)
ilist1(i) = ilist1(j)
ilist1(j) = temp
endif
If (Present(zlist1)) Then
ztemp = zlist1(i)
zlist1(i) = zlist1(j)
zlist1(j) = ztemp
endif
End If
End Do
End Do
Return
End Subroutine interchange_sort_d
!****************************************************************!******************************************************************************!
End Module
[Fortran] 纯文本查看 复制代码
program SortTest
use QuickSortMod
use qsort_c_module
implicit none
interface
subroutine qsort(a,length)bind(c,name="sort_integer")
use,intrinsic::iso_c_binding
integer(c_int),value::length
integer(c_int)::a(length)
end subroutine
end interface
integer::N,i
integer,allocatable::IntDat(:),intDat2(:),intdat3(:)
real,allocatable::dat(:)
real::start,finish
do i=1,7
N=10**i
if(allocated(intdat))deallocate(intdat)
if(allocated(intdat2))deallocate(intdat2)
if(allocated(dat))deallocate(dat)
if(allocated(intdat3))deallocate(intdat3)
allocate(IntDat(n),intDat2(n),dat(n),intdat3(n))
call random_seed()
call random_number(dat)
intDat = int((2*Dat-1)*100)
intdat2 = intdat
intdat3 = intdat
call cpu_time(start)
call quick_sort_i(intdat)
call cpu_time(finish)
write(*,*)"Fortran version of Quick Sort I"
write(*,'("Len of array:",i10," Time = ",f6.3," seconds.")')n,finish-start
call cpu_time(start)
call QsortC(intdat3)
call cpu_time(finish)
write(*,*)"Fortran version of Quick Sort II"
write(*,'("Len of array:",i10," Time = ",f6.3," seconds.")')n,finish-start
call cpu_time(start)
call qsort(intdat2,n)
call cpu_time(finish)
write(*,*)"Fortran call C version of qsort"
write(*,'("Len of array:",i10," Time = ",f6.3," seconds.")')n,finish-start
deallocate(intdat,intdat2,dat,intdat3)
enddo
end program