我一直在浏览有关此错误消息的已回答的问题。
我正在尝试解决使用二进制搜索查找某些索引的Rosalind web site中的问题。
当我的子程序找到它似乎忽略它的数字时,如果我尝试打印$found
变量,它会给我错误
使用严格的参考时,不能使用字符串“1”作为符号引用
代码是这个
sub binarysearch
{
my $numbertolook = shift;
my @intarray=@_;
my $lengthint = scalar @intarray;
my @sorted = sort {$a <=> $b} @intarray;
#print $numbertolook, " " , @sorted, "\n";
my $low=0;
my $high=$lengthint-1;
my $found =undef;
my $midpoint;
while ($low<$high)
{
$midpoint=int(($low+$high)/2);
#print $midpoint, " ",$low," ", $high, " ", @sorted, "\n";
if ($numbertolook<$sorted[$midpoint])
{
$high=$midpoint;
}
elsif ($numbertolook>$sorted[$midpoint])
{
$low=$midpoint;
}
elsif ($numbertolook==$sorted[$midpoint])
{
$found=1;
print $found "\n";
last;
}
if ($low==$high-1 and $low==$midpoint)
{
if ($numbertolook==$sorted[$high])
{
$found=1;
print $found "\n";
last;
}
$low=$high;
}
}
return $found;
}
答案 0 :(得分:3)
你想要
print $found, "\n";
或者
print $found . "\n";
$ found和换行符之间没有运算符,它认为$ found是打印换行符的文件句柄,并且因为它不是文件句柄而收到错误。
答案 1 :(得分:1)
如果使用空格分隔调用多个参数调用print,则第一个参数应为文件句柄。这是documentation的print FILEHANDLE LIST
。
print $found "\n";
您要做的就是与,
分开,将其称为print LIST
。
print $found, "\n";
或以字符串形式连接,也称为print LIST
,但LIST
只有一个元素。
print $found . "\n";
答案 2 :(得分:1)
我会尽力帮助
首先,尽管看起来很简单,但二进制搜索很难正确编码。主要原因是它是一个一个一个错误的温床,它是如此普遍,以至于它们有自己的Wikipedia page
问题在于,包含值A
到Z
的数组将包含26个元素,索引为0到25.我认为FORTRAN的趋势和Lua,但几乎每个其他语言在索引零处具有数组的第一个元素
在您开始使用divide and conquer algorithms之前,零基础适用于所有内容。合并排序以及二进制搜索都是这样的算法。二进制搜索
困难的部分是当你必须决定何时找到了这个物体,或者当你需要放弃寻找时。将数据分成两半几乎很容易。知道何时停止 hard
它对排序数据非常有效,但实现它时会出现问题,如果我们正确地执行它,我们必须处理超过零或一的所有类型的奇怪索引库。
假设我有一个数组
my @alpha = 'A' .. 'Q'
如果我print scalar @alpha
我会看到17,这意味着数组有17个元素,索引从0到16
现在我在那个数组中寻找E
,所以我进行二分搜索,所以我想要&#34;前半部分&#34;和#34;下半场&#34; @alpha
。如果我添加0到16并除以2,我得到一个整洁的&#34; 8&#34;,所以中间元素位于索引8,即H
但是等等。有17个元素,这是一个奇数,所以如果我们说前八个(A
.. H
)留在中间和后八个(I
.. { {1}})正好在中间,然后肯定是&#34;中间&#34;是Q
?
事实上,这完全是一种欺骗,因为二进制搜索会起作用,但我们会对数据进行分区。在这种情况下,二进制意味着两个部分,虽然如果这些部分的大小相等,搜索会更有效,但算法不需要工作。所以它可以是前三分之一和后三分之二,或者只是第一个元素和其余元素
这就是使用I
的原因。它向下舍入到最接近的整数,以便我们的17个元素数组int(($low+high)/2)
是可用的8而不是8.5
但是你的代码仍然要考虑一些意想不到的事情。在我们的17元素数组的情况下,我们计算出中间索引为8.因此索引0 .. 7是&#34;前半部分&#34;而8 ... 16是&#34;下半场&#34;,中间指数是下半场开始的地方
但我们没有围绕向下分区?因此,在奇数个元素的情况下,我们的中点不应该在上半部分的末尾,而不是第二个的开始?这是一个神秘的一个一个错误,但让我们看看它是否仍适用于简单的偶数个元素
$mid
开头和和索引是0和3;中间索引是@alpha = `A` .. `D`
== 1.所以前半部分是0..1而下半部分是2 .. 3.工作正常
但还有更多。假设我必须使用两个元素int((0+3)/2)
和X
搜索数组。这有两个明显的一半,我正在寻找Y
,这是在中间之前。所以我现在搜索A
的单元素列表X
。目标数组的最小和最大元素都为零。中点是A
== 0.那么接下来会发生什么?
当我们在同一个列表中搜索int((0+0)/2)
时,情况类似但更糟糕。代码必须完全正确,否则我们将搜索数组的末尾或一次又一次地检查最后一个元素
最后保存最差,假设
Z
我正在寻找my @alpha = ( 'A', 'B, 'Y, 'Z' )
。这样可以避免涉及检查的各种优化,这可能会使普通情况慢得多
由于所有这一切,它是使用库或语言内置函数来完成所有这些工作的最佳解决方案。特别是,Perl的哈希通常是检查特定字符串和任何相关数据所需的全部内容。使用的算法比任何非平凡数据集的二进制搜索要好得多。
维基百科显示this algorithm进行迭代二元搜索
二进制搜索算法也可以用两个索引限制迭代表示,这两个索引限制会逐渐缩小搜索范围。
M
这是您的代码版本,它远非无错误,但可以实现您的目标。你离这么远了
int binary_search(int A[], int key, int imin, int imax)
{
// continue searching while [imin,imax] is not empty
while (imin <= imax)
{
// calculate the midpoint for roughly equal partition
int imid = midpoint(imin, imax);
if (A[imid] == key)
// key found at index imid
return imid;
// determine which subarray to search
else if (A[imid] < key)
// change min index to search upper subarray
imin = imid + 1;
else
// change max index to search lower subarray
imax = imid - 1;
}
// key was not found
return KEY_NOT_FOUND;
}
use strict;
use warnings 'all';
print binarysearch( 76, 10 .. 99 ), "\n";
sub binarysearch {
my $numbertolook = shift;
my @intarray = @_;
my $lengthint = scalar @intarray;
my @sorted = sort { $a <=> $b } @intarray;
my $low = 0;
my $high = $lengthint - 1;
my $found = undef;
my $midpoint;
while ( $low < $high ) {
$midpoint = int( ( $low + $high ) / 2 );
#print $midpoint, " ",$low," ", $high, " ", @sorted, "\n";
if ( $numbertolook < $sorted[$midpoint] ) {
$high = $midpoint;
}
elsif ( $numbertolook > $sorted[$midpoint] ) {
$low = $midpoint;
}
elsif ( $numbertolook == $sorted[$midpoint] ) {
$found = 1;
print "FOUND\n";
return $midpoint;
}
if ( $low == $high - 1 and $low == $midpoint ) {
if ( $numbertolook == $sorted[$high] ) {
$found = 1;
print "FOUND\n";
return $midpoint;
}
return;
}
}
return $midpoint;
}