Arrays 如何根据升序列值对数组中的行进行排序?

Arrays 如何根据升序列值对数组中的行进行排序?,arrays,sorting,multidimensional-array,fortran,row,Arrays,Sorting,Multidimensional Array,Fortran,Row,例如,如果我有以下二维阵列: 2 1 4 1 2 3 2 1 2 要按每行排序,如何使用列值进行升序?在本例中,我能够对数组中的第一列进行排序,得到 1 2 3 2 1 4 2 1 2 在这个例子中,我的最终结果应该是: 1 2 3 2 1 2 2 1 4 首先,我想查看第一列,然后对行进行排序。因为两行以2开头,所以我想看看第二列,然后进行排序。如果这些数字仍然相同,我想看下一列,依此类推。我应该怎么做?您需要的是两个不同的过程: 一个是将两行相互比较并决定哪一

例如,如果我有以下二维阵列:

2   1   4
1   2   3
2   1   2
要按每行排序,如何使用列值进行升序?在本例中,我能够对数组中的第一列进行排序,得到

1 2 3
2 1 4
2 1 2 
在这个例子中,我的最终结果应该是:

1 2 3
2 1 2
2 1 4

首先,我想查看第一列,然后对行进行排序。因为两行以2开头,所以我想看看第二列,然后进行排序。如果这些数字仍然相同,我想看下一列,依此类推。我应该怎么做?

您需要的是两个不同的过程:

一个是将两行相互比较并决定哪一行应该提前,另一个是实际进行排序的

下面是一个版本,它使用的冒泡排序实现得很差:

program sort

    implicit none
    integer, parameter :: num_rows = 3
    integer, parameter :: num_cols = 3
    character(len=*), parameter :: fmt = '(3I4)'
    integer :: a(num_cols,num_rows)

    a = reshape([2, 1, 4, 1, 2, 3, 2, 1, 2], [3, 3])

    call sortrow(a)

    print fmt, a

contains

    subroutine sortrow(a)
        implicit none
        integer, intent(inout) :: a(num_cols, num_rows)
        integer :: i, j
        integer :: tmp(num_cols)
        do i = 1, num_rows
            do j = i+1, num_rows
                if (islarger(a(:,i), a(:,j))) then
                    tmp(:) = a(:, i)
                    a(:, i) = a(:, j)
                    a(:, j) = tmp(:)
                end if
            end do
        end do
    end subroutine sortrow

    function islarger(a, b)
        implicit none
        integer, intent(in) :: a(num_cols), b(num_cols)
        logical :: islarger
        integer :: i
        do i = 1, num_cols
            if (a(i) > b(i)) then
                islarger = .TRUE.
                return
            end if
            if (b(i) > a(i)) then
                islarger = .FALSE.
                return
            end if
        end do
        islarger = .FALSE.
        return
    end function islarger

end program sort
或者,您可以编写一个函数,将一行映射到单个整数值上,如果行n必须位于m之后,则n的此值大于m


例如,如果所有的值都是个位数(0到9),那么您可以将
[2,1,4]
转换为
214
,这将更容易排序。

我尝试了一种惰性的方法,即为。为了避免全局数据,我将比较函数作为调用
qsort
并保存要排序的数组的子例程的内部函数。中间子例程分配一个实际排序的索引数组
qsort
,然后索引数组用于拉直输入数组。下面是它的工作原理:

module sortmod
   use ISO_C_BINDING
   implicit none
   interface
      subroutine qsort(base,nitems,size,compar) bind(C,name='qsort')
         import
         implicit none
         type(C_PTR), value :: base
         integer(C_SIZE_T), value :: nitems
         integer(C_SIZE_T), value :: size
         interface
            function compar(x,y) bind(C)
               import
               implicit none
               integer(C_INT) compar
               type(C_PTR),value :: x
               type(C_PTR),value :: y
            end function compar
         end interface
      end subroutine qsort
   end interface
   contains
      recursive subroutine startsort(array)
         integer(C_INT) array(:,:)
         integer(C_INT), allocatable, target :: indices(:)
         integer i
         indices = [(i,i=1,size(array,1))]
         call qsort(C_LOC(indices),size(indices,1,kind=C_SIZE_T),C_SIZEOF(indices(1)),callback)
         array = array(indices,:)
         contains
            function callback(x,y) bind(C)
               integer(C_INT) callback
               type(C_PTR), value :: x, y
               integer(C_INT), pointer :: ix,iy
               integer j
               call C_F_POINTER(x,ix)
               call C_F_POINTER(y,iy)
               callback = 0
               do j = 1, size(array,2)
                  callback = array(ix,j) - array(iy,j)
                  if(callback /= 0) return
               end do
            end function callback
      end subroutine startsort
end module sortmod

program testsort
   use sortmod
   implicit none
   integer(C_INT), allocatable :: array(:,:)
   character(20) fmt
   array = reshape([2, 1, 4, &
                    1, 2, 3, &
                    2, 1, 2], &
                    [3, 3], order = [2, 1])
   call startsort(array)
   write(fmt,'(*(g0))') '(',size(array,2),'i3)'
   write(*,fmt) transpose(array)
end program testsort
gfortran的输出:

  1  2  3
  2  1  2
  2  1  4

您真的确定要在
qsort
接口中使用Fortran接口进行
compar
?我不认为这是严格正确的,互操作性没有保证。我只是使用了一个
c_funptr
@VladimirF,我阅读了标准的第18.3.7节,“如果。。。(5) 任何不带VALUE属性的伪参数都对应于指针类型原型的形式参数,并且该伪参数可与引用类型的实体进行互操作(ISO/IEC 9899:2011、6.25、7.19和7.20.1)另外,如果一个过程不能工作,为什么标准会让你把它作为一个实际的参数来传递呢?在这方面,它禁止其他不可能的语法。好吧,编译器允许各种不严格符合的东西,如果它们不打破约束的话。谢谢您的参考。@VladimirF我还讨论了是否将伪参数
x
y
声明为
函数比较
,而不是按值声明为
整数(C_INT)
。这将是更自然的Fortran接口,但我最终没有这样做,因为我认为编译器可能会优化对
C\F\u指针的调用,我不想因为必须解释您可能必须为
qsort()的每个上下文编写不同的接口体而混淆这个问题
。至少要呈现一些代码,这是很好的,甚至可以预期。现在你很幸运,你的问题得到了很好的回答,但这并不总是发生。很多人会否决你的问题,而不是为你写完整的代码。看见