Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Fortran deallocate linked lists?

I would like to use linked lists in Fortran to hold an array of data of an undefined length.

I have the following setup:

TYPE linked_list
    INTEGER :: data
    TYPE(linked_list) :: next_item => NULL()
END TYPE

Now say I create such a list:

TYPE(LINKED_LIST) :: example_list
example_list%data =1
ALLOCATE(example_list%next_item)
example_list%next_item%data = 2
ALLOCATE(example_list%next_item%next_item)
example_list%next_item%next_item%data = 3

My question is, if I perform:

DEALLOCATE(example_list)

will all the nested levels also be deallocated or do I need to traverse the list to the deepest element and deallocate from the deepest element upward?

like image 604
EMiller Avatar asked Feb 07 '12 22:02

EMiller


1 Answers

You have to deallocate each node manually. This is where "Object oriented" like style comes useful.

module LinkedListModule
    implicit none
    private

    public :: LinkedListType
    public :: New, Delete
    public :: Append

    interface New
        module procedure NewImpl
    end interface

    interface Delete
        module procedure DeleteImpl
    end interface

    interface Append
        module procedure AppendImpl
    end interface

    type LinkedListType
        type(LinkedListEntryType), pointer :: first => null()
    end type

    type LinkedListEntryType
        integer :: data
        type(LinkedListEntryType), pointer :: next => null()
    end type

contains

    subroutine NewImpl(self)
        type(LinkedListType), intent(out) :: self

        nullify(self%first) 
    end subroutine

    subroutine DeleteImpl(self)
       type(LinkedListType), intent(inout) :: self

       if (.not. associated(self%first)) return

       current => self%first
       next => current%next
       do
           deallocate(current)
           if (.not. associated(next)) exit
           current => next
           next => current%next
       enddo

    end subroutine

    subroutine AppendImpl(self, value)

       if (.not. associated(self%first)) then
           allocate(self%first)
           nullify(self%first%next)
           self%first%value = value
           return
       endif


       current => self%first
       do
           if (associated(current%next)) then
               current => current%next
           else
             allocate(current%next)
             current => current%next
             nullify(current%next)
             current%value = value
             exit
           endif
       enddo

    end subroutine

end module

Beware: it's past midnight and I'm not really fond of coding in a browser window. This code may not work. It's just a layout.

Use like this

program foo
   use LinkedListModule
   type(LinkedListType) :: list

   call New(list)
   call Append(list, 3)
   call Delete(list)
end program
like image 71
Stefano Borini Avatar answered Oct 05 '22 17:10

Stefano Borini