Octopus
linked_list.F90
Go to the documentation of this file.
1! Copyright (C) 2019-2020 M. Oliveira
2!!
3!! This Source Code Form is subject to the terms of the Mozilla Public
4!! License, v. 2.0. If a copy of the MPL was not distributed with this
5!! file, You can obtain one at https://mozilla.org/MPL/2.0/.
6!!
7
8#include "global.h"
9
13 use global_oct_m
15 implicit none
16
17 private
18 public :: &
21 list_t, &
25
26 !---------------------------------------------------------------------------
36 type :: linked_list_t
37 private
38 integer, public :: size = 0
39 class(list_node_t), pointer :: first_node => null()
40 class(list_node_t), pointer :: last_node => null()
41 contains
42 procedure :: add_node => linked_list_add_node
43 procedure :: add_ptr => linked_list_add_node_ptr
44 procedure :: add_copy => linked_list_add_node_copy
45 procedure :: delete => linked_list_delete_node
46 procedure :: has => linked_list_has
47 procedure :: copy => linked_list_copy
48 generic :: assignment(=) => copy
49 procedure :: empty => linked_list_empty
50 final :: linked_list_finalize
51 end type linked_list_t
52
58
60 private
61 class(list_node_t), pointer :: next_node => null()
62 contains
63 procedure :: start => linked_list_iterator_start
64 procedure :: has_next => linked_list_iterator_has_next
65 procedure :: get_next_ptr => linked_list_iterator_get_next_ptr
67
68 !---------------------------------------------------------------------------
91 type, extends(linked_list_t) :: list_t
92 private
93 contains
94 procedure :: add => list_add_node
95 end type list_t
96
98 contains
99 procedure :: get_next => list_iterator_get_next
100 end type list_iterator_t
101
102 !---------------------------------------------------------------------------
106 type, extends(linked_list_t) :: integer_list_t
107 private
108 contains
109 procedure :: add => integer_list_add_node
110 end type integer_list_t
111
113 contains
114 procedure :: get_next => integer_iterator_get_next
115 end type integer_iterator_t
116
117contains
118
119 ! Linked list
120 ! ---------------------------------------------------------
122 subroutine linked_list_add_node(this, value, clone)
123 class(linked_list_t), intent(inout) :: this
124 class(*), target :: value
125 logical, intent(in) :: clone
126
127 class(list_node_t), pointer :: new_node
128
129 if (.not. associated(this%first_node)) then
130 this%first_node => list_node_t(value, this%first_node, clone)
131 this%last_node => this%first_node
132 else
133 new_node => list_node_t(value, this%last_node%next(), clone)
134 call this%last_node%set_next(new_node)
135 this%last_node => new_node
136 end if
137 this%size = this%size + 1
139 end subroutine linked_list_add_node
141 ! ---------------------------------------------------------
143 subroutine linked_list_add_node_ptr(this, value)
144 class(linked_list_t), intent(inout) :: this
145 class(*), target :: value
146
147 call this%add_node(value, clone=.false.)
148
149 end subroutine linked_list_add_node_ptr
150
151 ! ---------------------------------------------------------
153 subroutine linked_list_add_node_copy(this, value)
154 class(linked_list_t), intent(inout) :: this
155 class(*), target :: value
157 call this%add_node(value, clone=.true.)
159 end subroutine linked_list_add_node_copy
160
161 ! ---------------------------------------------------------
163 subroutine linked_list_delete_node(this, value)
164 class(linked_list_t), intent(inout) :: this
165 class(*), target :: value
166
167 class(list_node_t), pointer :: previous, current, next
168
169 previous => null()
170 current => null()
171 next => this%first_node
172 do while (associated(next))
173 previous => current
174 current => next
175 next => next%next()
176 if (current%is_equal(value)) then
177 if (associated(next) .and. .not. associated(previous)) then
178 ! First node
179 this%first_node => next
180 else if (.not. associated(next) .and. associated(previous)) then
181 ! Last node
182 call previous%set_next(null())
183 this%last_node => previous
184 else if (.not. associated(next) .and. .not. associated(previous)) then
185 ! List only has one node
186 nullify(this%first_node)
187 nullify(this%last_node)
188 else
189 ! Neither the first nor the last node
190 call previous%set_next(next)
191 end if
192 deallocate(current)
193 this%size = this%size - 1
194 exit
195 end if
196 end do
197
198 end subroutine linked_list_delete_node
200 ! ---------------------------------------------------------
201 subroutine linked_list_finalize(this)
202 type(linked_list_t), intent(inout) :: this
203
204 call this%empty()
206 end subroutine linked_list_finalize
208 ! ---------------------------------------------------------
209 subroutine linked_list_empty(this)
210 class(linked_list_t), intent(inout) :: this
211
212 class(list_node_t), pointer :: current, next
213
214 current => this%first_node
215 do while (associated(current))
216 next => current%next()
217 deallocate(current)
218 current => next
219 end do
220 nullify(this%first_node)
221 nullify(this%last_node)
222 this%size = 0
223
224 end subroutine linked_list_empty
225
226 ! ---------------------------------------------------------
227 subroutine linked_list_copy(lhs, rhs)
228 class(linked_list_t), intent(out) :: lhs
229 class(linked_list_t), intent(in) :: rhs
230
231 class(list_node_t), pointer :: current, new_node
232
233 current => rhs%first_node
234 do while (associated(current))
235 if (.not. associated(lhs%first_node)) then
236 lhs%first_node => current%copy(lhs%first_node)
237 lhs%last_node => lhs%first_node
238 else
239 new_node => current%copy(lhs%last_node%next())
240 call lhs%last_node%set_next(new_node)
241 lhs%last_node => new_node
242 end if
243 current => current%next()
244 end do
245 lhs%size = rhs%size
247 end subroutine linked_list_copy
248
249 ! ---------------------------------------------------------
250 logical function linked_list_has(this, value)
251 class(linked_list_t), intent(inout) :: this
252 class(*), target :: value
253
254 class(list_node_t), pointer :: current
255
256 current => this%first_node
257 linked_list_has = .false.
258 do while (associated(current) .and. .not. linked_list_has)
259 linked_list_has = current%is_equal(value)
260 current => current%next()
261 end do
262
263 end function linked_list_has
264
265 ! ---------------------------------------------------------
266 subroutine linked_list_iterator_start(this, list)
267 class(linked_list_iterator_t), intent(inout) :: this
268 class(linked_list_t), target, intent(in) :: list
269
270 this%next_node => list%first_node
271
272 end subroutine linked_list_iterator_start
273
274 ! ---------------------------------------------------------
275 logical function linked_list_iterator_has_next(this)
276 class(linked_list_iterator_t), intent(in) :: this
277
278 linked_list_iterator_has_next = associated(this%next_node)
279
281
282 ! ---------------------------------------------------------
283 function linked_list_iterator_get_next_ptr(this) result(value)
284 class(linked_list_iterator_t), intent(inout) :: this
285 class(*), pointer :: value
286
287 value => this%next_node%get()
288 this%next_node => this%next_node%next()
289
291
292
293 ! Unlimited polymorphic list
295 ! ---------------------------------------------------------
296 subroutine list_add_node(this, value)
297 class(list_t), intent(inout) :: this
298 class(*), target :: value
299
300 call this%add_ptr(value)
301
302 end subroutine list_add_node
303
304 ! ---------------------------------------------------------
305 function list_iterator_get_next(this) result(value)
306 class(list_iterator_t), intent(inout) :: this
307 class(*), pointer :: value
308
309 value => this%get_next_ptr()
310
311 end function list_iterator_get_next
312
313 ! Integer list
314
315 ! ---------------------------------------------------------
316 subroutine integer_list_add_node(this, value)
317 class(integer_list_t), intent(inout) :: this
318 integer, target :: value
319
320 call this%add_copy(value)
321
322 end subroutine integer_list_add_node
323
324 ! ---------------------------------------------------------
325 function integer_iterator_get_next(this) result(value)
326 class(integer_iterator_t), intent(inout) :: this
327 integer :: value
328
329 select type (ptr => this%get_next_ptr())
330 type is (integer)
331 value = ptr
332 class default
333 assert(.false.)
334 end select
335
336 end function integer_iterator_get_next
337
338end module linked_list_oct_m
This module implements fully polymorphic linked lists, and some specializations thereof.
subroutine linked_list_add_node_ptr(this, value)
add data by pointer to the list
subroutine linked_list_add_node_copy(this, value)
add data by copying to the list
subroutine linked_list_iterator_start(this, list)
subroutine integer_list_add_node(this, value)
subroutine list_add_node(this, value)
logical function linked_list_iterator_has_next(this)
subroutine linked_list_add_node(this, value, clone)
add a node to the linked list
class(*) function, pointer list_iterator_get_next(this)
subroutine linked_list_copy(lhs, rhs)
class(*) function, pointer linked_list_iterator_get_next_ptr(this)
subroutine linked_list_finalize(this)
subroutine linked_list_empty(this)
logical function linked_list_has(this, value)
integer function integer_iterator_get_next(this)
subroutine linked_list_delete_node(this, value)
delete a node from the list
This module implements a node of a polymorphic linked list.
Definition: list_node.F90:105
This class implements a linked list of integer values.
This class implements an iterator for the polymorphic linked list.
This class implements a linked list of unlimited polymorphic values.
This class implements a linked list of unlimited polymorphic values.
class for a node in a polymorphic linked list
Definition: list_node.F90:115
int true(void)