找回密码
 注册
Simdroid-非首页
查看: 85|回复: 2

[3. Fortran] 用Fortran实现向量的增长与向量元素的删除和插入

[复制链接]
发表于 2008-11-7 21:56:39 | 显示全部楼层 |阅读模式 来自 黑龙江哈尔滨
c++中的STL库中的vector向量类在向量中任何位置都可以插入和删除单元。基本功能list一样了,比list的优势在于还能随机读取,太方便了。Fortran能不能实现呢?下面给出实现的一种方式,该方法适用于任何的数据类型,所以有些近似于c++模板的功能。


下面是个对c++ vector类的Fortran模拟,如果向量中没有指针,该方法是合适的!!

文件 vector.f90

type VECTOR
    private
    integer                                  :: no_used
    type(VECTOR_DATA), dimension(:), pointer :: data    => null()
end type VECTOR

private
public :: VECTOR, VECTOR_DATA
public :: vector_create, vector_append, vector_at, &
          vector_size, vector_put, vector_delete_elements, &
          vector_destroy, vector_insert_empty

real, parameter :: growth_rate = 1.1

contains

! vector_create
!     Create a new vector
!
! Arguments:
!     vec           Variable that should hold the vector
!     capacity      Initial capacity (optional)
!
! Note:
!     The fields of the vector data structure are set
!
subroutine vector_create( vec, capacity )
    type(VECTOR)       :: vec
    integer, optional  :: capacity

    integer            :: cap

    !
    ! Check that the vector does not have any data left
    !
    if ( associated(vec%data) ) then
        call vector_destroy( vec )
    endif

    if ( present(capacity) ) then
        cap = max( 1, capacity )
    else
        cap = 10
    endif
    allocate( vec%data(1:cap) )
    vec%no_used = 0
end subroutine vector_create

! vector_destroy
!     Destroy a vector
!
! Arguments:
!     vec           Vector in question
!
subroutine vector_destroy( vec )
    type(VECTOR)       :: vec

    !
    ! Check that the vector does not have any data left
    !
    if ( associated(vec%data) ) then
        deallocate( vec%data )
    endif
    vec%no_used = 0
end subroutine vector_destroy

! vector_size
!     Return the number of elements in use
!
! Arguments:
!     vec           Variable that holds the vector
!
integer function vector_size( vec )
    type(VECTOR)       :: vec

    vector_size = vec%no_used
end function vector_size

! vector_at
!     Get the value of the nth element of the vector
!
! Arguments:
!     vec           Vector in question
!     n             Index of the element whose value
!                   should be retrieved
!
type(VECTOR_DATA) function vector_at( vec, n )
    type(VECTOR)       :: vec
    integer            :: n

    if ( n .lt. 1 .or. n .gt. vec%no_used ) then
        vector_at = empty_vector_data
    else
        vector_at = vec%data(n)
    endif
end function vector_at

! vector_insert_empty
!     Insert one or more empty elements
!
! Arguments:
!     vector        Vector in question
!     pos           Position to insert the empty elements
!     number        Number of empty elements
!
subroutine vector_insert_empty( vec, pos, number )
    type(VECTOR)         :: vec
    integer, intent(in)  :: pos
    integer, intent(in)  :: number

    integer              :: i

    if ( number .lt. 1 .or. pos .lt. 1 .or. pos .gt. vec%no_used ) then
        return
    endif

    if ( vec%no_used+number .ge. size(vec%data) ) then
        call vector_increase_capacity( vec, vec%no_used+number )
    endif

    do i = vec%no_used,pos,-1
        vec%data(i+number) = vec%data(i)
    enddo

    do i = 1,number
        vec%data(pos+i-1) = empty_vector_data
    enddo

    vec%no_used = vec%no_used + number
end subroutine vector_insert_empty

! vector_delete_elements
!     Delete one or more elements
!
! Arguments:
!     vector        Vector in question
!     pos           Position to start deletion
!     number        Number of elements
!
subroutine vector_delete_elements( vec, pos, number )
    type(VECTOR)         :: vec
    integer, intent(in)  :: pos
    integer, intent(in)  :: number

    integer              :: i

    if ( number .lt. 1 .or. pos .lt. 1 .or. pos .gt. vec%no_used ) then
        return
    endif

    do i = pos,vec%no_used-number
        vec%data(i) = vec%data(i+number)
    enddo

    vec%no_used = vec%no_used - number
end subroutine vector_delete_elements



! vector_append
!     Append a value to the vector
!
! Arguments:
!     vec           Vector in question
!     data          Data to be appended
!
subroutine vector_append( vec, data )
    type(VECTOR)       :: vec
    type(VECTOR_DATA)  :: data

    if ( vec%no_used .ge. size(vec%data) ) then
        call vector_increase_capacity( vec, vec%no_used+1 )
    endif

    vec%no_used = vec%no_used + 1
    vec%data(vec%no_used) = data
end subroutine vector_append

! vector_put
!     Put a value at a specific element of the vector
!     (it needs not yet exist)
!
! Arguments:
!     vec           Vector in question
!     n             Index of the element
!     data          Data to be put in the vector
!
subroutine vector_put( vec, n, data )
    type(VECTOR)       :: vec
    integer            :: n
    type(VECTOR_DATA)  :: data

    if ( n .lt. 1 ) then
        return
    endif
    if ( n .gt. size(vec%data) ) then
        call vector_increase_capacity( vec, n )
    endif

    vec%no_used = max( vec%no_used, n)
    vec%data(n) = data
end subroutine vector_put

! vector_increase_capacity
!     Expand the array holding the data
!
! Arguments:
!     vec           Vector in question
!     capacity      Minimum capacity
!
subroutine vector_increase_capacity( vec, capacity )
    type(VECTOR)       :: vec
    integer            :: capacity

    integer            :: new_cap
    type(VECTOR_DATA), dimension(:), pointer :: new_data

    new_cap = max( capacity, nint( growth_rate * size(vec%data) ) )

    if ( new_cap .gt. size(vec%data) ) then
        allocate( new_data(1:new_cap) )
        new_data(1:vec%no_used) = vec%data(1:vec%no_used)
        new_data(vec%no_used+1:new_cap) = empty_vector_data

        deallocate( vec%data )
        vec%data => new_data
    endif

end subroutine vector_increase_capacity





主程序文件 main.f90

module DATA_MODULE

type REAL_DATA
    real :: value
end type REAL_DATA

type(REAL_DATA), parameter :: empty_data = REAL_DATA(-999.0)

end module DATA_MODULE

!
! Module defining the vector type
!
module REAL_VECTORS
    use DATA_MODULE, VECTOR_DATA => REAL_DATA, &
                     empty_vector_data => empty_data

    include "vector.f90"
end module REAL_VECTORS

program test_vectors
    use REAL_VECTORS

    implicit none

    type(VECTOR)      :: vector1
    type(VECTOR_DATA) :: data
    integer           :: i

    !
    ! Create a vector and set some elements
    !
    call vector_create( vector1, 2 )

    do i = 1,10
       data%value = i
       call vector_put( vector1, i, data )
    enddo

    write(*,*) 'Contents of the vector: numbers 1 to 10'

    do i = 1,vector_size(vector1)
        write(*,*) i, vector_at(vector1,i)
    enddo

    !
    ! Insert an element in the middle
    !
    call vector_insert_empty( vector1, 5, 3 )
    data%value = 3.1415926
    call vector_put( vector1, 5, data )

    write(*,*) 'Contents of the vector: 1 to 4, pi, two empty, 5 to 10'

    do i = 1,vector_size(vector1)
        write(*,*) i, vector_at(vector1,i)
    enddo

    !
    ! Append an element at the end
    !
    data%value = exp(1.0)
    call vector_append( vector1, data )

    write(*,*) 'Contents of the vector: plus e'

    do i = 1,vector_size(vector1)
        write(*,*) i, vector_at(vector1,i)
    enddo

    !
    ! Delete the two empty entries
    !
    call vector_delete_elements( vector1, 6, 2 )

    write(*,*) 'Contents of the vector: minus the empty ones'

    do i = 1,vector_size(vector1)
        write(*,*) i, vector_at(vector1,i)
    enddo

end program





[ 本帖最后由 zhoulon 于 2008-11-10 08:10 编辑 ]

评分

1

查看全部评分

 楼主| 发表于 2008-11-7 22:03:25 | 显示全部楼层 来自 黑龙江哈尔滨
Simdroid开发平台
笑脸比较郁闷啊

[ 本帖最后由 lishhit 于 2008-11-7 22:05 编辑 ]
回复 不支持

使用道具 举报

发表于 2008-11-10 08:08:38 | 显示全部楼层 来自 大连理工大学
不错,感谢发表原创帖子,还望继续努力,争取更好地提高和活跃版面的人气。呵呵,我帮你编辑了一下。

[ 本帖最后由 zhoulon 于 2008-11-10 08:11 编辑 ]
回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Simapps系列直播

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-11-1 13:29 , Processed in 0.033036 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表