我正在尝试实施二进制搜索。这是我的代码:
#!/usr/bin/perl
#use strict;
use warnings;
@array = (1..100);
$number = <STDIN>;
$low = 0;
$high = $#array;
while($low < $high){
print "Searcing $low ---- $high \n";
$mid = $low + ($high - $low)/2;
if($array[$mid] == $number){
print "Found in index:" . $mid;
last;
}
elsif($array[$mid] < $number){
$low = $mid + 1;
}
else{
$high = $mid - 1;
}
}
但它不起作用,虽然它是一个简单的实现(至少它将在Java中)
似乎我在划分时得到浮点值并且无法搜索。如果我提供输入5
,我会得到垃圾:
5
Searcing 0 ---- 99
Searcing 0 ---- 48.5
Searcing 0 ---- 23.25
Searcing 0 ---- 10.625
Searcing 0 ---- 4.3125
Searcing 3.15625 ---- 4.3125
如何让它使用整数,以便我可以索引数组?
此外,如果我取消注释use strict
,我会收到以下错误。他们的意思是什么?
Global symbol "@array" requires explicit package name at D:\Development\Perl\chapter3\binarySearch.pl line 6.
Global symbol "$number" requires explicit package name at D:\Development\Perl\chapter3\binarySearch.pl line 9.
Global symbol "$low" requires explicit package name at
答案 0 :(得分:6)
my $int = int 5 / 2;
print $int;
打印2。
答案 1 :(得分:3)
两个深奥的解决方案。除非你真的很无聊或其他什么,否则不要使用这些。
use integer
- 一个强制Perl将所有数值视为整数的pragma。它可以是本地范围的,因此它不会破坏程序中的所有数据
while($low < $high){
print "Searcing $low ---- $high \n";
{
use integer;
$mid = $low + ($high - $low)/2;
}
if($array[$mid] == $number){
print "Found in index:" . $mid;
last;
}
elsif($array[$mid] < $number){
$low = $mid + 1;
}
else{
$high = $mid - 1;
}
}
Perl有一些特殊变量$=
,$-
和$%
,它们只保存整数值,无论你赋予它们什么。直接使用它们
$- = $low + ($high - $low) / 2;
if ($array[$-] == $number) { ...
或作为中间体
my $mid = $- = $low + ($high - $low) / 2;
if ($array[$mid] == $number) { ...
使用这样的魔术变量对于code golf来说很方便,并且会激怒你的同事,但其他的并不多。
答案 2 :(得分:2)
您应该使用int函数。
除此之外,您需要use strict;
并使用my
来确定变量的范围。这将捕获您可能错过的错误。只需声明它们:
my @array = (1..100);
chomp(my $number = <STDIN>);
my $low = 0;
my $high = $#array;
my $mid = int ($low + ($high - $low)/2);
您也可以考虑使用chomp来删除输入中的换行符。
答案 3 :(得分:2)
使用优质的>> 1
代替/2
。
示例:
perl -e 'BEGIN { print 5/2, " : ", 5>>1}'
输出:
2.5 : 2
并使用(备用减法):
my $mid = ($low + $high) >> 1;
答案 4 :(得分:2)
您的代码存在很多问题。
您已停用strict。
大概是因为下一个问题。
our @array = 1..100;
use vars qw'$mid $low $high';
my $number = <STDIN>
你太担心溢出了。这不是C.
如果你的数字会溢出一个整数,它就会变成一个浮点数。
my $mid = $low + ($high - $low)/2;
应该只是:
my $mid = ($high + $low)/2;
你期望得到一个除法之外的整数。
my $mid = ($high + $low)/2;
如果你真的想要一个整数,只需使用int
。
my $mid = int( ($high + $low)/2 );
您没有从$number
chomp($number);
你有一个错误。
while($low < $high){
应该是
while($low <= $high){
这确实是你的主要问题。
#! /usr/bin/env perl
use strict;
use warnings;
my @array = 1..100;
my $number = <STDIN>;
chomp $number;
my $low = 0;
my $high = $#array;
while($low <= $high){
my $mid = int( ($high + $low)/2 );
printf "Searching %2d .. (%2d) .. %2d\n", $low, $mid, $high;
if($array[$mid] == $number){
print "Found $number at index mid $mid\n";
last;
}elsif($array[$mid] < $number){
$low = $mid + 1;
}else{
$high = $mid - 1;
}
}
虽然不是真的Perlish。
#!/usr/bin/perl
use strict;
use warnings;
use List::MoreUtils qw'first_index';
my @array = 1..100;
my $number = <STDIN>;
chomp $number;
my $index = first_index { $_ == $number } @array;
print "Found $number at index ", $index if $index != -1;
或者更奇怪
#! /usr/bin/env perl
use strict;
use warnings;
my @array = 1..100;
my $number = <STDIN>;
chomp $number;
my $char = join '', map chr, @array;
my $index = index $char, chr $number;
print "Found $number at index $index\n" if $index != -1;
这适用于UV
max或(2 ** 72) - 1
中较小的数字
在64位版本上是18,446,744,073,709,551,615,在32位版本上是4,294,967,295。
答案 5 :(得分:1)
首先,
my $mid = $low + ($high - $low)/2
可以简化为
my $mid = ($high + $low)/2;
您可以使用int
my $mid = int( ($high + $low)/2 );
或者你可以利用位移是整数除以2的事实。
my $mid = ($high + $low) >> 1;