Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion 如何在fortran中完成递归二进制搜索?_Recursion_Fortran_Binary Search - Fatal编程技术网

Recursion 如何在fortran中完成递归二进制搜索?

Recursion 如何在fortran中完成递归二进制搜索?,recursion,fortran,binary-search,Recursion,Fortran,Binary Search,我试图在排序数组中找到包含值I的最小索引。如果这个i值不存在,我希望返回-1。我正在使用一个二进制搜索递归子程序。问题是我不能真正停止这种递归,我得到了很多答案(一个正确,其余的错误)。有时我会遇到一个叫做“分段错误:11”的错误,但我并没有得到任何结果 我已经尝试删除这个调用随机数,因为我的主程序中已经有一个排序数组,但它不起作用 program main implicit none integer, allocatable :: A(:) real

我试图在排序数组中找到包含值I的最小索引。如果这个i值不存在,我希望返回-1。我正在使用一个二进制搜索递归子程序。问题是我不能真正停止这种递归,我得到了很多答案(一个正确,其余的错误)。有时我会遇到一个叫做“分段错误:11”的错误,但我并没有得到任何结果

我已经尝试删除这个调用随机数,因为我的主程序中已经有一个排序数组,但它不起作用

 program main
  implicit none
  integer, allocatable      :: A(:)
  real                      :: MAX_VALUE
  integer                   :: i,j,n,s, low, high
  real                      :: x

  N= 10                !size of table
  MAX_VALUE = 10

  allocate(A(n))

  s = 5          ! searched value
  low = 1        ! lower limit
  high = n       ! highest limit


  !generate random table of numbers (from 0 to 1000)
  call Random_Seed
  do i=1, N
     call Random_Number(x)  !returns random x >= 0 and <1
   A(i)= anint(MAX_VALUE*x)
  end do

 call bubble(n,a)
 print *,' '
 write(*,10) (a(i),i=1,N)
 10 format(10i6)

 call bsearch(A,n,s,low,high)

 deallocate(A)

end program main
气泡子例程:

subroutine sort(p,q)

    implicit none
    integer(kind=4), intent(inout)      :: p, q
    integer(kind=4)                  :: temp

    if (p>q) then
       temp = p
       p = q
       q = temp
    end if
    return
end subroutine sort
subroutine bubble(n,arr)

 implicit none
 integer(kind=4), intent(inout)        :: n
 integer(kind=4), intent(inout)        :: arr(n)
 integer(kind=4)                       :: sorted(n)
 integer                               :: i,j

do i=1, n
   do j=n, i+1, -1
      call sort(arr(j-1), arr(j))
   end do
end do
return

end subroutine bubble

recursive subroutine bsearch(b,n,i,low,high)

   implicit none
   integer(kind=4)       ::    b(n)
   integer(kind=4)       ::    low, high
   integer(kind=4)       ::    i,j,x,idx,n
   real(kind=4)          ::    r

   idx = -1

   call random_Number(r)
   x = low + anint((high - low)*r)

   if (b(x).lt.i) then
   low = x + 1
   call bsearch(b,n,i,low,high)

   else if (b(x).gt.i) then
      high = x - 1
      call bsearch(b,n,i,low,high)
   else
   do j = low, high
    if (b(j).eq.i) then
       idx = j
       exit
    end if
    end do
  end if

 ! Stop if high = low
    if (low.eq.high) then
    return
   end if

   print*, i, 'found at index ', idx
   return

   end subroutine bsearch
目标是获得与线性搜索相同的结果。但我得到了这两个答案中的任何一个

排序表:

     1     1     2     4     5     5     6     7     8    10

       5 found at index            5
       5 found at index           -1
       5 found at index           -1
或者如果找不到该值

   2     2     3     4     4     6     6     7     8     8  

   Segmentation fault: 11

有两个问题导致递归搜索例程
bsearch
停止并产生不需要的输出,或者导致分段错误。简单地按照您提供的示例中的程序执行逻辑,说明问题:

1)存在和找到的值,不需要的输出
首先,考虑第一个例子,其中数组<代码> b>代码>包含值<代码> i=5 < /Cord>您正在搜索(在下面的代码块的前两行中用<代码> < <代码> >指出的值和索引)。使用符号
Rn
表示递归的
n
第四个级别,
L
H
表示下限和上限,以及
x
表示当前指数估计,给定的代码运行可能如下所示:

b(x): 1     1     2     4    |5|    5     6     7     8    10
x:    1     2     3     4    |5|    6     7     8     9    10
R0:   L                                         x          H
R1:   Lx                                  H
R2:         L                       x     H

    5 found at index            5
    5 found at index           -1
    5 found at index           -1
b(x): 2     2     3     4     4     6     6     7     8     8
x:    1     2     3     4     5     6     7     8     9     10
R0:   L                 x                                   H
R1:                           L                       x     H
R2:                           L     x           H
R3:                          LxH
R4:                           H     xL
.
.
.

Segmentation fault: 11
在R0和R1中,
b(x).lt.i
b(x).gt.i
中的
b(x).gt.i
b搜索
中起到了缩短搜索间隔的作用。在R2中,执行
else
分支中的
do
-循环,
idx
被分配正确的值,并按预期打印。但是,现在遇到了一个
return
语句,它将-在本例中是第一个R1(!),其中执行将在
if-else-if-else
块之后恢复,从而以
idx=-1
的初始值将消息打印到屏幕上。从R0返回主程序时也会发生同样的情况。这解释了您看到的(不需要的)输出

2)值不存在,分段错误 其次,考虑示例导致分割错误。使用与前面相同的符号,可能的运行可能如下所示:

b(x): 1     1     2     4    |5|    5     6     7     8    10
x:    1     2     3     4    |5|    6     7     8     9    10
R0:   L                                         x          H
R1:   Lx                                  H
R2:         L                       x     H

    5 found at index            5
    5 found at index           -1
    5 found at index           -1
b(x): 2     2     3     4     4     6     6     7     8     8
x:    1     2     3     4     5     6     7     8     9     10
R0:   L                 x                                   H
R1:                           L                       x     H
R2:                           L     x           H
R3:                          LxH
R4:                           H     xL
.
.
.

Segmentation fault: 11
在R0到R2中,搜索间隔再次按预期缩短。然而,在R3中,逻辑失败。由于数组
b
中不存在搜索值
i
,因此
.lt.
.gt.
测试中的一个将始终计算为
.true.
,这意味着
的测试为低.eq。high
终止搜索,但从未到达。从这一点开始,逻辑不再有效(例如,
high
可以小于
low
),代码将继续深化递归级别,直到调用堆栈变得太大,出现分段错误

这些解释了代码中的主要逻辑缺陷。一种可能的低效方法是使用
do
-循环查找包含搜索值的最低索引。考虑一个你寻找的值是例如<代码> i=8 < /COD>,并且它出现在数组中的最后一个位置,如下所示。进一步假设其位置的第一个猜测是
x=high
。这意味着您的代码将立即分支到
do
-循环,在该循环中几乎对整个数组进行线性搜索,以找到最终结果
idx=9
。虽然正确,但预期的二进制搜索会变成线性搜索,这可能会导致性能降低

b(x): 2     2     3     4     4     6     6     7    |8|    8
x:    1     2     3     4     5     6     7     8    |9|    10
R0:   L                                                     xH

    8 found at index            9
解决问题 至少,您应该将
移动到low.eq。high
测试到
bsearch
例程的开始,以便在定义无效边界之前停止递归(然后需要额外测试以查看是否找到搜索值)。另外,在搜索成功后立即通知,即在
do
-循环中的相等性测试或刚才提到的附加测试之后。这仍然不能解决可能的线性搜索效率低下的问题

考虑到所有因素,您最好阅读查找“最左边”索引的算法(例如,在a上或在a上-这里的两个示例都使用迭代而不是递归,可能是另一种改进,但适用相同的原则),并将其应用于Fortran,这可能类似于此(仅显示新代码,
参考示例中的现有代码):


其中,从
minloc
返回的
j
将是数组
a
中的最低索引,其中可以找到
s
,并在
a(j)时用于返回
j
==s
-1
否则。

请使用tag,您会得到更多关注。请用它制作一个完整的可编译程序。我还怀疑
b搜索
例程中缺少一些声明,请显式添加它们(还有
隐式无
,这样就不会忘记。当删除
随机数
时,
r
使用哪个值。最好为您的子例程提供显式接口。将它们放在模块中或使它们成为内部的(在
包含
之后和
结束程序
之前)。这将启用一些编译器检查。此外,当您遇到类似的崩溃时,您应该始终启用编译器检查,如
gfortran-Wall-fcheck=all-g-fbacktrace
或编译器的等效项。这一点非常重要。您当前的代码无法编译。它会在编译时产生许多错误。您必须显示实际代码,a。另外,关于模块的问题,没有co,我不能说什么