! Recursive Fortran 95 quicksort routine ! sorts real numbers into ascending numerical order ! Author: Juli Rew, SCD Consulting (juliana@ucar.edu), 9/03 ! Based on algorithm from Cormen et al., Introduction to Algorithms, ! 1997 printing ! Made F conformant by Walt Brainerd ! !Updated 2016 Tue !The RealQsort now uses real*8 instead of real. ! ! Dec 2016 KRA, added integer version ! module mQuickSort implicit none public :: RealQsortC private :: RealPartition public :: IntQsortC private :: IntPartition interface IntPartition module procedure IntPartition_real,IntPartition_complex,IntPartition_int end interface interface IntQsortC module procedure IntQsortC_complex, IntQsortC_real, IntQsortC_int end interface contains recursive subroutine RealQsortC(A) real*8, intent(in out), dimension(:) :: A integer :: iq if(size(A) > 1) then call RealPartition(A, iq) call RealQsortC(A(:iq-1)) call RealQsortC(A(iq:)) endif end subroutine RealQsortC subroutine RealPartition(A, marker) real*8, intent(in out), dimension(:) :: A integer, intent(out) :: marker integer :: i, j real*8 :: temp real*8 :: x ! pivot point x = A(1) i= 0 j= size(A) + 1 do j = j-1 do if (A(j) <= x) exit j = j-1 end do i = i+1 do if (A(i) >= x) exit i = i+1 end do if (i < j) then ! exchange A(i) and A(j) temp = A(i) A(i) = A(j) A(j) = temp elseif (i == j) then marker = i+1 return else marker = i return endif end do end subroutine RealPartition recursive subroutine IntQsortC_int(SortInts,Secondarys) integer, intent(inout), dimension(:) :: SortInts integer, intent(inout), dimension(:) :: Secondarys integer :: iq if(size(SortInts) > 1) then call IntPartition(SortInts,Secondarys, iq) call IntQsortC(SortInts(:iq-1),Secondarys(:iq-1)) call IntQsortC(SortInts(iq:),Secondarys(iq:)) endif end subroutine IntQsortC_int recursive subroutine IntQsortC_real(SortInts,Secondarys) integer, intent(inout), dimension(:) :: SortInts real*8, intent(inout), dimension(:) :: Secondarys integer :: iq if(size(SortInts) > 1) then call IntPartition(SortInts,Secondarys, iq) call IntQsortC(SortInts(:iq-1),Secondarys(:iq-1)) call IntQsortC(SortInts(iq:),Secondarys(iq:)) endif end subroutine IntQsortC_real recursive subroutine IntQsortC_complex(SortInts,Secondarys) integer, intent(inout), dimension(:) :: SortInts complex*16, intent(inout), dimension(:) :: Secondarys integer :: iq if(size(SortInts) > 1) then call IntPartition(SortInts,Secondarys, iq) call IntQsortC(SortInts(:iq-1),Secondarys(:iq-1)) call IntQsortC(SortInts(iq:),Secondarys(iq:)) endif end subroutine IntQsortC_complex subroutine IntPartition_int(SortInts, Secondarys,marker) integer, intent(inout), dimension(:) :: SortInts integer, intent(inout), dimension(:) :: Secondarys integer, intent(out) :: marker integer :: i, j integer :: temp real*8 :: rtemp integer :: x ! pivot point x = SortInts(1) i= 0 j= size(SortInts) + 1 do j = j-1 do if (SortInts(j) <= x) exit j = j-1 end do i = i+1 do if (SortInts(i) >= x) exit i = i+1 end do if (i < j) then ! exchange A(i) and A(j) temp = SortInts(i) SortInts(i) = SortInts(j) SortInts(j) = temp rtemp=Secondarys(i) Secondarys(i)=Secondarys(j) Secondarys(j)=rtemp elseif (i == j) then marker = i+1 return else marker = i return endif end do end subroutine IntPartition_int subroutine IntPartition_real(SortInts, Secondarys,marker) integer, intent(inout), dimension(:) :: SortInts real*8, intent(inout), dimension(:) :: Secondarys integer, intent(out) :: marker integer :: i, j integer :: temp real*8 :: rtemp integer :: x ! pivot point x = SortInts(1) i= 0 j= size(SortInts) + 1 do j = j-1 do if (SortInts(j) <= x) exit j = j-1 end do i = i+1 do if (SortInts(i) >= x) exit i = i+1 end do if (i < j) then ! exchange A(i) and A(j) temp = SortInts(i) SortInts(i) = SortInts(j) SortInts(j) = temp rtemp=Secondarys(i) Secondarys(i)=Secondarys(j) Secondarys(j)=rtemp elseif (i == j) then marker = i+1 return else marker = i return endif end do end subroutine IntPartition_real subroutine IntPartition_complex(SortInts, Secondarys,marker) integer, intent(inout), dimension(:) :: SortInts complex*16, intent(inout), dimension(:) :: Secondarys integer, intent(out) :: marker integer :: i, j integer :: temp complex*16 :: rtemp integer :: x ! pivot point x = SortInts(1) i= 0 j= size(SortInts) + 1 do j = j-1 do if (SortInts(j) <= x) exit j = j-1 end do i = i+1 do if (SortInts(i) >= x) exit i = i+1 end do if (i < j) then ! exchange A(i) and A(j) temp = SortInts(i) SortInts(i) = SortInts(j) SortInts(j) = temp rtemp=Secondarys(i) Secondarys(i)=Secondarys(j) Secondarys(j)=rtemp elseif (i == j) then marker = i+1 return else marker = i return endif end do end subroutine IntPartition_complex end module mQuickSort