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()的每个上下文编写不同的接口体而混淆这个问题
。至少要呈现一些代码,这是很好的,甚至可以预期。现在你很幸运,你的问题得到了很好的回答,但这并不总是发生。很多人会否决你的问题,而不是为你写完整的代码。看见