基于fortran的TimSort排序算法,最快的排序算法

基于fortran的TimSort排序算法,最快的排序算法


0. 引言

   Timsort是一种混合排序算法,它结合了插入排序和归并排序的思想。它由Tim Peters在2002年为Python编程语言开发而来,并被应用于Java的Arrays.sort方法和Python的sorted函数中。

Timsort基本原理如下:

1. 首先将要排序的数组分割成大小相等的块,这些块被称为run。每个run都可以使用插入排序进行排序。

2. 排序后的run会被合并成更大的run,直到所有的run都被合并为一个run。合并操作使用归并排序的方式进行。

3. 为了提高效率,Timsort使用了一种优化的合并策略,称为galloping mode(飞跃模式)。当两个run进行合并时,如果其中一个run的元素在另一个run中都找不到比它小的元素,那么可以直接将整个run复制到目标数组中,而不需要逐个比较和复制元素。这种策略可以显著提高排序效率。

4. 在合并的过程中,Timsort还会根据已经排序好的块的大小选择合适的合并方式。比如,当合并两个run时,如果其中一个run的长度是另一个run的2倍以上,那么可以直接将较短的run插入到较长的run的合适位置,而不需要使用归并排序。

   Timsort时间复杂度为O(n log n),其中n是要排序的元素的个数。它的性能在实际应用中表现良好尤其是对于有序或部分有序的数组。

   总结起来,Timsort是一种结合了插入排序归并排序思想的排序算法。它使用分块、合并和优化的合并策略来提高排序效率

1. 代码实现及示例

  生成一个随机一维向量,调用module文件下的timSort函数进行排列,timSort函数的一般形式为:

subroutine timSort(arr)

其中arr为输入输出(inout)变量,输出的即为排序后的结果。下面是timSort排序算法示例

! test timSort

program main
    use, intrinsic ::  iso_fortran_env
    use base_math
    real(real64),allocatable :: array(:),array2(:),array3(:)
    real(real64) :: t_beg,t_end,t_sample
    integer(int32) :: i
    
    allocate( array(12) ) ! 假定数组长度为12
    call random_seed
    call random_number(array) ! 生成随机数组
    
    array3 =array 
    call cpu_time(t_beg)
    call timSort(array3)  
    call cpu_time(t_end)
    t_Tim = t_end - t_beg
    
    print *,"    排序前  ","    排序后"
    do i = 1, size(array)
        write(*, '(f12.7,1X,f12.7,1X,f12.7)')array(i),array3(i)
    enddo
end program

   执行结果如下,能够看到arrayarray3分别为排序前和排序后的数组。在排序数组长度较长是,也具有较好的效率,可以说是目前最高效的排序算法。


   下面是module文件,包含timSort排序算法的主要过程

module base_math
use, intrinsic ::  iso_fortran_env
implicit none
    
contains  

subroutine insertionSort(arr, left, right)
implicit none
real(real64),intent(inout) :: arr(0:)
integer(int32),intent(in) :: left,right
integer(int32) :: i,j
real(real64) :: temp

do i = left + 1, right
    temp = arr(i)
    j = i - 1
    do while (j >= left)
        if( arr(j) <= temp )exit
        arr(j+1) = arr(j)
        j = j-1
    enddo
    arr(j+1) = temp
enddo
end subroutine insertionSort


subroutine merge(arr, l, m, r)  
    implicit none
    real(real64),dimension(0:) :: arr
    integer(int32) :: l,m,r
    integer(int32) :: len1,len2,i,j,k
    real(real64),allocatable,dimension(:) ::left,right
    
    len1 = m - l + 1
    len2 = r - m
    allocate(left(0:len1-1))
    allocate(right(0:len2-1))  
    do i = 0, len1-1  
        left(i) = arr(l + i)
    enddo
    
    do i = 0, len2-1  
        right(i) = arr(m + 1 + i)  
    enddo
    
    i = 0  
    j = 0  
    k = l  

    do while (i < len1 .and. j < len2)  
        if (left(i) <= right(j))then  
            arr(k) = left(i)  
            i = i + 1
        else  
            arr(k) = right(j)  
            j = j+1 
        endif
        k = k + 1 
    enddo

    do while (i < len1)  
        arr(k) = left(i)  
        k = k + 1  
        i=i+1  
    enddo

    do while (j < len2)  
        arr(k) = right(j)  
        k = k +1  
        j = j +1  
    enddo
end subroutine

! 排序算法
subroutine timSort(arr)
    implicit none
    real(real64),dimension(0:) :: arr
    integer(int32) :: i,size1,left,mid,right,n
    integer(int32),parameter :: minRun = 32

    n = size(arr)    
    !minRun = calcMinRun(n)
    
    do i = 0, n-1, minRun
        call insertionSort(arr, i, min((i+minRun-1),(n-1)))
    enddo

    size1 = minRun
    do while(size1 < n)
        do left = 0,n,2 * size1
            mid = min(n - 1, left + size1 - 1)
            right = min((left + 2 * size1 - 1), (n - 1))
            if (mid < right)then
                call merge(arr, left, mid, right)
            endif
        enddo
        size1 = 2 * size1  
    enddo
end subroutine timSort
    
end module base_math

2. 排序算法执行效率对比

   前篇已介绍过简单排序算法和快速排序算法,那加上本篇的timSort算法,三种排序算法效率如何❓下面模拟一个chang数组进行排序并计时,可以直观3种算法的效率。

program main
    use, intrinsic ::  iso_fortran_env
    use base_math
! 效率对比
    real(real64),allocatable :: array(:),array2(:),array3(:)
    integer :: i
    integer(int32) :: t_beg,t_end,t_sample,t_quick,t_Tim
    real(real64),allocatable,dimension(:) :: arr
    
    allocate( array(100000) ) ! 假定数组长度为32
    call random_seed
    call random_number(array) ! 生成随机数组
    
    call system_clock(t_beg)
    array2 = sort_simple(array) 
    call system_clock(t_end)
    t_sample = t_end - t_beg
    
    array3 =array 
    call system_clock(t_beg)
    call timSort(array3)  
    call system_clock(t_end)
    t_Tim = t_end - t_beg
    
    call system_clock(t_beg)
    call QuickSort(array) !> 快速排序
    call system_clock(t_end)
    t_quick = t_end - t_beg
    
    print *,"排序耗时对比:"
    print *,"sample=",t_sample,"quick=",t_quick,"t_Tim=",t_Tim
    print *,""
    print *,"数组array排序结果:"
    do i = 1, 100
        write(*, '(f12.7,1X,f12.7,1X,f12.7)')array2(i),array(i),array3(i)
    enddo
end program

   对比发现,quickSort排序算法与TimSort算法运行效率相差不大,整体TimSort稍微快些,可能存在写法问题不能真实反应运行效率,这里做为示例,后续有机会再对TimSort算法做一些优化再进行比较。

在这里插入图片描述

3. 代码实现及示例

   本篇分享了fortran代码写的TimSort 排序算法,能够实现对一维向量的正确排列。






😜
😜😜
😜😜😜😜

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咋(za)说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值