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
| 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 (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
|