FV3 Bundle
quicksort.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 #undef _TYP
20 #define _TYP integer
21 
22 ! Written by Magnus Lie Hetland
23 
24 function qksrt_partition(n, list, start, end) result(top)
25  implicit none
26  integer, intent(in) :: n
27  _typ, intent(inout) :: list(n)
28  integer, intent(in) :: start, end
29 
30  integer pivot, bottom, top
31  logical done
32 
33  pivot = list(end) ! Partition around the last value
34  bottom = start-1 ! Start outside the area to be partitioned
35  top = end ! Ditto
36 
37  done = .false.
38  do while (.not. done) ! Until all elements are partitioned...
39 
40  do while (.not. done) ! Until we find an out of place element...
41  bottom = bottom+1 ! ... move the bottom up.
42 
43  if(bottom == top) then ! If we hit the top...
44  done = .true. ! ... we are done.
45  exit
46  endif
47 
48  if(list(bottom) > pivot) then ! Is the bottom out of place?
49  list(top) = list(bottom) ! Then put it at the top...
50  exit ! ... and start searching from the top.
51  endif
52  enddo
53 
54  do while (.not. done) ! Until we find an out of place element...
55  top = top-1 ! ... move the top down.
56 
57  if(top == bottom) then ! If we hit the bottom...
58  done = .true. ! ... we are done.
59  exit
60  endif
61 
62  if(list(top) < pivot) then ! Is the top out of place?
63  list(bottom) = list(top) ! Then put it at the bottom...
64  exit ! ...and start searching from the bottom.
65  endif
66  enddo
67  enddo
68 
69  list(top) = pivot ! Put the pivot in its place.
70  ! Return the split point
71 
72 end function qksrt_partition
73 
74 recursive subroutine qksrt_quicksort(n, list, start, end)
75  implicit none
76  integer, intent(in) :: n
77  _typ, intent(inout) :: list(n)
78  integer, intent(in) :: start, end
79  integer :: split, qksrt_partition
80  external :: qksrt_partition
81  if(start < end) then ! If there are two or more elements...
82  split = qksrt_partition(n, list, start, end) ! ... partition the sublist...
83  call qksrt_quicksort(n, list, start, split-1) ! ... and sort both halves.
84  call qksrt_quicksort(n, list, split+1, end)
85  endif
86 end subroutine qksrt_quicksort
87 
88 
89 #ifdef _TEST_SORT
90  program test
91  implicit none
92  integer :: list(16) = (/6, 2, 3, 4, 1, 45, 3432, 3245, 32545, 66555, 32, 1,3, -43254, 324, 54/)
93  print *,'before list=', list
94  call qksrt_quicksort(size(list), list, 1, size(list))
95  print *,'after list=', list
96  end program test
97 #endif
recursive subroutine qksrt_quicksort(n, list, start, end)
Definition: quicksort.F90:75
integer function qksrt_partition(n, list, start, end)
Definition: quicksort.F90:25