sort.f90 Source File


Files dependent on this one

sourcefile~~sort.f90~~AfferentGraph sourcefile~sort.f90 sort.f90 sourcefile~kdtree.f90 kdTree.f90 sourcefile~kdtree.f90->sourcefile~sort.f90 sourcefile~sort_test.f90 sort_test.f90 sourcefile~sort_test.f90->sourcefile~sort.f90 sourcefile~kdtree_test.f90 kdTree_test.f90 sourcefile~kdtree_test.f90->sourcefile~kdtree.f90 sourcefile~unstructuredgrid.f90 unstructuredGrid.f90 sourcefile~kdtree_test.f90->sourcefile~unstructuredgrid.f90 sourcefile~unstructuredgrid.f90->sourcefile~kdtree.f90 sourcefile~boxflowfield.f90 boxFlowField.f90 sourcefile~boxflowfield.f90->sourcefile~unstructuredgrid.f90 sourcefile~cellcentercalc_test.f90 cellCenterCalc_test.f90 sourcefile~cellcentercalc_test.f90->sourcefile~unstructuredgrid.f90 sourcefile~dropletmotionsimulation.f90 dropletMotionSimulation.f90 sourcefile~dropletmotionsimulation.f90->sourcefile~unstructuredgrid.f90 sourcefile~flow_field.f90 flow_field.f90 sourcefile~dropletmotionsimulation.f90->sourcefile~flow_field.f90 sourcefile~flow_field.f90->sourcefile~unstructuredgrid.f90 sourcefile~main.f90 MAIN.f90 sourcefile~main.f90->sourcefile~dropletmotionsimulation.f90

Contents

Source Code


Source Code

module sort_m
    !!author: Shohei Kishi, Hikaru Konishi, Tatsuya Miyoshi, Yuta Ida
    !!ソートモジュール
    implicit none
    private

    !>コンテンツ構造体
    !>実数とIDをメンバに持つ
    type, public :: content_t
        integer originID
        real value
    end type

    !>ヒープ木クラス
    !>実体は単なる配列だがツリー構造を表現している
    !>要素 i に注目すると、親ノードは要素 i/2(小数切り捨て) であり、子ノードは要素 2i, 2i + 1 である
    type HeapTree
        type(content_t), allocatable :: node(:)

        contains

        procedure totalHeaplification!, partialHeaplification
        procedure rebuild_tree!, get_featuredChildID
        
    end type

    public heap_sort
    public real2content
    public merge_sort

    contains

    !>ヒープ木のコンストラクタ
    type(HeapTree) function HeapTree_(array)
        type(content_t), intent(in) :: array(:)

        HeapTree_%node = array

        call HeapTree_%totalHeaplification()

    end function

    !>全体ヒープ化(親子の大小関係解決)メソッド
    subroutine totalHeaplification(self)
        class(HeapTree) self
        integer num_node
        integer parentID, child1ID, child2ID!, featuredChildID

        num_node = size(self%node)
            
        do parentID = num_node/2, 1, -1 !子を持つノードに対してのみ下(葉の方)からループ

            child1ID = parentID*2
            child2ID = parentID*2 + 1

            ! featuredChildID = self%get_featuredChildID(child1ID, child2ID)
            !これ使わんほうが速い

            if(self%node(parentID)%value > self%node(child1ID)%value) call swap_content(self%node, parentID, child1ID)

            if(child2ID <= num_node) then
                if(self%node(parentID)%value > self%node(child2ID)%value) call swap_content(self%node, parentID, child2ID)
            end if

        end do

    end subroutine

    !入れ替えの起こった部分だけヒープ化(親子の大小関係解決)メソッド
    !こっちのほうが速いと思うが、現在バグってます
    ! subroutine partialHeaplification(self)
    !     class(HeapTree) self
    !     integer parentID, child1ID, child2ID, featuredChildID
    !     integer num_node

    !     num_node = size(self%node)

    !     parentID = 1

    !     do

    !         child1ID = parentID*2
    !         if(child1ID > num_node) exit    !第一子すら存在しなければループ終了
    !         child2ID = parentID*2 + 1

    !         featuredChildID = self%get_featuredChildID(child1ID, child2ID)

    !         if(self%node(parentID)%value > self%node(featuredChildID)%value) then
    !             call swap_content(self%node, parentID, featuredChildID)
    !             parentID = featuredChildID
    !         else
    !             exit    !入れ替えが起こらなければループ終了
    !         end if

    !     end do

    ! end subroutine

    subroutine rebuild_tree(self)
        !!根ノードを除去し、ノード配列を左詰めにする。
        !!このとき、配列のサイズが一つ減る。
        class(HeapTree) self

        self%node = self%node(2:)

    end subroutine

    subroutine swap_content(array, ID1, ID2)
        integer, intent(in) :: ID1, ID2
        type(content_t), intent(inout) :: array(:)
        type(content_t) temp !一時的に格納する変数

        temp = array(ID1)
        array(ID1) = array(ID2)
        array(ID2) = temp

    end subroutine

    ! function get_featuredChildID(self, child1ID, child2ID) result(featuredChildID)
    !     class(HeapTree) self
    !     integer, intent(in) :: child1ID, child2ID
    !     integer featuredChildID
        
    !     if(child2ID <= size(self%node)) then 
    !         !第2子が存在する(配列サイズ内)場合
    !         !値の小さい方を返す
    !         if (self%node(child1ID)%value < self%node(child2ID)%value) then
    !             featuredChildID = child1ID
    !         else
    !             featuredChildID = child2ID
    !         end if

    !         !self%node(:)%valueの臨時配列生成に時間がかかってたぽい
    !         ! featuredChildID = get_smallerID(self%node(:)%value, child1ID, child2ID)

    !     else
    !         !第2子が存在しない(配列サイズ外)場合
    !         featuredChildID = child1ID  

    !     end if
    
    ! end function

    ! function get_smallerID(array, ID1, ID2) result(smaller_ID)
    !     real,intent(in) :: array(:)
    !     integer, intent(in) :: ID1, ID2
    !     integer smaller_ID

    !     if (array(ID1) < array(ID2)) then
    !         smaller_ID = ID1
    !     else
    !         smaller_ID = ID2
    !     end if
    
    ! end function

    !>ヒープソート
    function heap_sort(array_origin) result(array_sorted)
        type(content_t), intent(in) :: array_origin(:)
        type(content_t) array_sorted(size(array_origin))
        type(HeapTree) heap_tree
        integer i

        heap_tree = HeapTree_(array_origin)

        do i = 1, size(array_origin)    !ソート後の配列に格納するループ
            array_sorted(i) = heap_tree%node(1)

            call heap_tree%rebuild_tree()

            call heap_tree%totalHeaplification()
            ! call heap_tree%partialHeaplification()

        end do

    end function

    !>実数型配列をコンテンツ配列に変換する
    function real2content(real_array) result(content_array)
        real, intent(in) :: real_array(:)
        type(content_t), allocatable :: content_array(:)
        integer i

        allocate(content_array(size(real_array)))

        do i = 1, size(real_array)
            content_array(i)%originID = i
            content_array(i)%value = real_array(i)
        end do

    end function

    function merge_sort(array_origin) result(array_sorted)
        !!マージソート
        type(content_t), intent(in) :: array_origin(:)
        type(content_t) array_sorted(size(array_origin))

        array_sorted = array_origin
        call merge_sort_recursive(array_sorted, 1, size(array_sorted))

    end function

    recursive subroutine merge_sort_recursive(array, left_end, right_end)
        type(content_t), intent(inout) :: array(:)
        integer, intent(in) :: left_end, right_end
        type(content_t), allocatable :: work_array(:)
        integer mid, i,j,k

        allocate(work_array(size(array)))
        
        if(left_end < right_end) then
            mid = int((left_end + right_end)/2)
            call merge_sort_recursive(array, left_end, mid)
            call merge_sort_recursive(array, mid+1, right_end)
            
            do i = mid, left_end, -1
                work_array(i) = array(i)           
            end do

            do j = mid+1, right_end
                work_array(right_end-(j-(mid+1))) = array(j)
            end do

            i = left_end
            j = right_end

            do k = left_end, right_end
                if(work_array(i)%value < work_array(j)%value) then
                    array(k) = work_array(i)
                    i = i + 1
                else
                    array(k) = work_array(j)
                    j = j - 1
                end if
            end do

        end if

    end subroutine

end module sort_m