例如,如果我有以下2D数组:
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开头,我想查看第二列,然后排序。如果那些仍然是相同的数字,我想看下一栏等等。我该怎么做?
答案 0 :(得分:1)
您需要的是两个不同的程序:
将两行相互比较并决定哪一行应该更早出现,另一行实际进行排序。
以下是使用实施不当的冒泡排序的版本:
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
,这将更容易排序。
答案 1 :(得分:0)
我尝试了将接口写入standard C library subroutine qsort
的懒惰方法。为了避免全局数据,我将比较函数作为调用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