Data update
This commit is contained in:
parent
4bb20c9b71
commit
cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions
|
|
@ -1,51 +1,123 @@
|
|||
INTEGER FUNCTION FINDELEMENT(K,A,N) !I know I can.
|
||||
Chase an order statistic: FindElement(N/2,A,N) leads to the median, with some odd/even caution.
|
||||
Careful! The array is shuffled: for i < K, A(i) <= A(K); for i > K, A(i) >= A(K).
|
||||
Charles Anthony Richard Hoare devised this method, as related to his famous QuickSort.
|
||||
INTEGER K,N !Find the K'th element in order of an array of N elements, not necessarily in order.
|
||||
INTEGER A(N),HOPE,PESTY !The array, and like associates.
|
||||
INTEGER L,R,L2,R2 !Fingers.
|
||||
L = 1 !Here we go.
|
||||
R = N !The bounds of the work area within which the K'th element lurks.
|
||||
DO WHILE (L .LT. R) !So, keep going until it is clamped.
|
||||
HOPE = A(K) !If array A is sorted, this will be rewarded.
|
||||
L2 = L !But it probably isn't sorted.
|
||||
R2 = R !So prepare a scan.
|
||||
DO WHILE (L2 .LE. R2) !Keep squeezing until the inner teeth meet.
|
||||
DO WHILE (A(L2) .LT. HOPE) !Pass elements less than HOPE.
|
||||
L2 = L2 + 1 !Note that at least element A(K) equals HOPE.
|
||||
END DO !Raising the lower jaw.
|
||||
DO WHILE (HOPE .LT. A(R2)) !Elements higher than HOPE
|
||||
R2 = R2 - 1 !Are in the desired place.
|
||||
END DO !And so we speed past them.
|
||||
IF (L2 - R2) 1,2,3 !How have the teeth paused?
|
||||
1 PESTY = A(L2) !On grit. A(L2) > HOPE and A(R2) < HOPE.
|
||||
A(L2) = A(R2) !So swap the two troublemakers.
|
||||
A(R2) = PESTY !To be as if they had been in the desired order all along.
|
||||
2 L2 = L2 + 1 !Advance my teeth.
|
||||
R2 = R2 - 1 !As if they hadn't paused on this pest.
|
||||
3 END DO !And resume the squeeze, hopefully closing in K.
|
||||
IF (R2 .LT. K) L = L2 !The end point gives the order position of value HOPE.
|
||||
IF (K .LT. L2) R = R2 !But we want the value of order position K.
|
||||
END DO !Have my teeth met yet?
|
||||
FINDELEMENT = A(K) !Yes. A(K) now has the K'th element in order.
|
||||
END FUNCTION FINDELEMENT !Remember! Array A has likely had some elements moved!
|
||||
!------------------------------------------------------------------------------
|
||||
! Module: quickselect_mod
|
||||
!
|
||||
! Description:
|
||||
! Hoare's QuickSelect algorithm: find the K-th smallest element in an
|
||||
! unsorted integer array in average O(N) time.
|
||||
!
|
||||
! The array is partially sorted as a side effect: on return,
|
||||
! A(i) <= A(K) for all i < K
|
||||
! A(i) >= A(K) for all i > K
|
||||
! so A(K) holds the K-th order statistic.
|
||||
!
|
||||
! Useful special cases:
|
||||
! K = 1 : minimum element
|
||||
! K = N : maximum element
|
||||
! K = (N+1)/2 : lower median
|
||||
!
|
||||
! The pivot at each step is A(K) itself. Because K lies within the search
|
||||
! window [L,R] at every iteration, A(K) is always a valid partition value
|
||||
! and the window narrows by at least one element per pass.
|
||||
!
|
||||
! Average time: O(N). Worst case: O(N^2) when the pivot is always extreme
|
||||
! (e.g., already-sorted input). For robust median finding on large arrays
|
||||
! consider Introselect (median-of-medians pivot selection).
|
||||
!
|
||||
! Reference:
|
||||
! C.A.R. Hoare, "Algorithm 65: Find", Communications of the ACM, 1961.
|
||||
!
|
||||
! Authors:
|
||||
! Original algorithm: C.A.R. Hoare
|
||||
!
|
||||
!------------------------------------------------------------------------------
|
||||
|
||||
PROGRAM POKE
|
||||
INTEGER FINDELEMENT !Not the default type for F.
|
||||
INTEGER N !The number of elements.
|
||||
PARAMETER (N = 10) !Fixed for the test problem.
|
||||
INTEGER A(66) !An array of integers.
|
||||
DATA A(1:N)/9, 8, 7, 6, 5, 0, 1, 2, 3, 4/ !The specified values.
|
||||
module quickselect_mod
|
||||
implicit none
|
||||
private
|
||||
public :: quickselect
|
||||
|
||||
WRITE (6,1) A(1:N) !Announce, and add a heading.
|
||||
1 FORMAT ("Selection of the i'th element in order from an array.",/
|
||||
1 "The array need not be in order, and may be reordered.",/
|
||||
2 " i Val:Array elements...",/,8X,666I2)
|
||||
contains
|
||||
|
||||
DO I = 1,N !One by one,
|
||||
WRITE (6,2) I,FINDELEMENT(I,A,N),A(1:N) !Request the i'th element.
|
||||
2 FORMAT (I3,I4,":",666I2) !Match FORMAT 1.
|
||||
END DO !On to the next trial.
|
||||
!---------------------------------------------------------------------------
|
||||
! quickselect -- return the K-th smallest element of A(1:N).
|
||||
!
|
||||
! The array A is partially rearranged in place; see module header.
|
||||
!---------------------------------------------------------------------------
|
||||
integer function quickselect(k, a, n)
|
||||
integer, intent(in) :: k ! order position wanted (1-based)
|
||||
integer, intent(in) :: n ! number of elements
|
||||
integer, intent(inout) :: a(n) ! array; partially sorted on exit
|
||||
|
||||
END !That was easy.
|
||||
integer :: l, r, l2, r2 ! outer and inner scan fingers
|
||||
integer :: pivot ! partition value (= A(K) each pass)
|
||||
integer :: tmp ! swap temporary
|
||||
|
||||
l = 1
|
||||
r = n
|
||||
|
||||
do while (l < r)
|
||||
pivot = a(k) ! A(K) lies in [L,R], so this is always valid.
|
||||
l2 = l
|
||||
r2 = r
|
||||
|
||||
! Partition loop: squeeze l2 and r2 inward until they cross.
|
||||
! Invariant: A(L..l2-1) < pivot, A(r2+1..R) > pivot.
|
||||
do while (l2 <= r2)
|
||||
|
||||
! Advance left finger past elements already in the right place.
|
||||
do while (a(l2) < pivot)
|
||||
l2 = l2 + 1
|
||||
end do
|
||||
|
||||
! Retreat right finger past elements already in the right place.
|
||||
do while (pivot < a(r2))
|
||||
r2 = r2 - 1
|
||||
end do
|
||||
|
||||
! l2 and r2 have stalled on out-of-order elements (or met).
|
||||
if (l2 <= r2) then
|
||||
if (l2 < r2) then ! stalled on two elements: swap them
|
||||
tmp = a(l2)
|
||||
a(l2) = a(r2)
|
||||
a(r2) = tmp
|
||||
end if
|
||||
l2 = l2 + 1 ! advance past the (now correct) pair
|
||||
r2 = r2 - 1
|
||||
end if
|
||||
|
||||
end do
|
||||
|
||||
! After partition, r2 < l2.
|
||||
! r2 is the final position of the last element <= pivot.
|
||||
! l2 is the final position of the first element >= pivot.
|
||||
! Narrow the outer window to the side that contains K.
|
||||
if (r2 < k) l = l2
|
||||
if (k < l2) r = r2
|
||||
|
||||
end do
|
||||
|
||||
quickselect = a(k)
|
||||
|
||||
end function quickselect
|
||||
|
||||
end module quickselect_mod
|
||||
|
||||
program poke
|
||||
use quickselect_mod
|
||||
implicit none
|
||||
integer :: i
|
||||
integer, parameter :: n = 10 !Fixed for the test problem.
|
||||
integer :: a(66) !An array of integers.
|
||||
data a(1:n)/9, 8, 7, 6, 5, 0, 1, 2, 3, 4/ !The specified values.
|
||||
|
||||
write(6, 1) a(1:n) !Announce, and add a heading.
|
||||
1 format("Selection of the i'th element in order from an array.", /, "The array need not be in order, and may be reordered.", & /, (*(i0, 1x)))
|
||||
2 format(t11, "i Val:Array elements...")
|
||||
3 format(t8, I3, I4, ":", (*(I0, 1x)))
|
||||
write(6, 2)
|
||||
do i = 1, n !One by one,
|
||||
write(6, 3) i, quickselect(i, a, n), a(1:n) !Request the i'th element.
|
||||
|
||||
end do
|
||||
|
||||
end program poke
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue