1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
| ! From http://www-h.eng.cam.ac.uk/help/mjg17/f90/mergsort.f90
MODULE Sort
CONTAINS
RECURSIVE SUBROUTINE Module_merge_sort (a, ascend)
IMPLICIT NONE
INTEGER, DIMENSION(:), INTENT(INOUT) :: a
LOGICAL, INTENT(IN), OPTIONAL :: ascend
LOGICAL :: up
INTEGER low, high, mid
! If 'ascend' parameter is not specified, then default sort to ascending order
IF (PRESENT(ascend)) THEN
up = ascend
ELSE
up = .TRUE.
ENDIF
low=LBOUND(a,1)
high=UBOUND(a,1)
IF (low<high) THEN
mid=(low+high)/2
CALL Module_merge_sort(a(low:mid), up)
CALL Module_merge_sort(a(mid+1:high), up)
a(low:high) = Merge(a(low:mid), a(mid+1:high), up)
END IF
END SUBROUTINE Module_merge_sort
FUNCTION Merge (a, b, up)
INTEGER, DIMENSION(:), INTENT(INOUT) :: a, b
INTEGER, DIMENSION(SIZE(a)+SIZE(b)) :: Merge
LOGICAL, INTENT(IN) :: up
INTEGER a_ptr, a_high, a_low
INTEGER b_ptr, b_high, b_low
INTEGER c_ptr
LOGICAL condition
a_low=LBOUND(a,1)
a_high=UBOUND(a,1)
b_low=LBOUND(b,1)
b_high=UBOUND(b,1)
a_ptr=a_low
b_ptr=b_low
c_ptr=1
DO WHILE (a_ptr<=a_high .AND. b_ptr<=b_high)
IF (up) THEN
condition= (a(a_ptr) <= b(b_ptr))
ELSE
condition= (a(a_ptr) >= b(b_ptr))
END IF
IF (condition) THEN
Merge(c_ptr)=a(a_ptr)
a_ptr=a_ptr+1
ELSE
Merge(c_ptr)=b(b_ptr)
b_ptr=b_ptr+1
END IF
c_ptr = c_ptr + 1
END DO
IF (a_ptr>a_high) THEN
Merge(c_ptr:) = b(b_ptr:b_high)
ELSE
Merge(c_ptr:) = a(a_ptr:a_high)
END IF
END FUNCTION Merge
END MODULE Sort
PROGRAM Merge_sort
USE Sort
INTEGER, DIMENSION(:), ALLOCATABLE :: array
INTEGER i, n
REAL r, time
PRINT*, "Enter array size:"
READ(*,*) n
ALLOCATE( array(n) )
DO i=1, n
CALL RANDOM_NUMBER(r)
array(i)=100 * r
END DO
PRINT '(20I3)', array(1:20)
time = Second()
CALL Module_merge_sort(array)
PRINT '("[Sort time = ",F10.3," seconds ]")', Second() - time
PRINT '(20I3)', array(1:20)
time = Second()
CALL Module_merge_sort(array, .FALSE.)
PRINT '("[Sort time = ",F10.3," seconds ]")', Second() - time
PRINT '(20I3)', array(1:20)
CONTAINS
REAL FUNCTION Second()
IMPLICIT NONE
INTEGER i, timer_count_rate, timer_count_max
CALL SYSTEM_CLOCK( i, timer_count_rate, timer_count_max )
Second = REAL(i) / timer_count_rate
END FUNCTION Second
END PROGRAM Merge_sort
|