Perl合并排序-数组引用
我试图在Perl中实现合并排序,我对Perl非常陌生,我知道我在数组引用方面做了一些错误的事情。处理完成后,数组最终会保存相同的值。请帮忙,因为我看不出我错在哪里 更正后的代码:Perl合并排序-数组引用,perl,sorting,mergesort,Perl,Sorting,Mergesort,我试图在Perl中实现合并排序,我对Perl非常陌生,我知道我在数组引用方面做了一些错误的事情。处理完成后,数组最终会保存相同的值。请帮忙,因为我看不出我错在哪里 更正后的代码: use strict; use warnings; my ( @aref, @auxref ) = (); my ( $hi, $lo, $i, $j, $k, $n ) = 0; @aref = ( 5, 7, 6, 3, 4, 1, 8, 9, 4 ); $n = @aref; mergeSort( \@are
use strict;
use warnings;
my ( @aref, @auxref ) = ();
my ( $hi, $lo, $i, $j, $k, $n ) = 0;
@aref = ( 5, 7, 6, 3, 4, 1, 8, 9, 4 );
$n = @aref;
mergeSort( \@aref, \@auxref, 0, $n - 1 );
print "@auxref\n";
print "@aref\n";
sub mergeSort {
my ($aref) = $_[0];
my ($auxref) = $_[1];
my $lo = $_[2];
my $hi = $_[3];
if ( $hi <= $lo ) { return; }
my $mid = 0;
$mid = int( $lo + ( $hi - $lo ) / 2 );
mergeSort( $aref, $auxref, $lo, $mid );
mergeSort( $aref, $auxref, $mid + 1, $hi );
merge( $aref, $auxref, $lo, $mid, $hi );
}
sub merge {
my ($aref) = $_[0];
my ($auxref) = $_[1];
my $lo = $_[2];
my $mid = $_[3];
my $hi = $_[4];
for ( $i = $lo ; $i <= $hi ; $i++ ) {
$auxref->[$i] = $aref->[$i];
}
$i = $lo;
$j = $mid + 1;
for ( $k = $lo ; $k <= $hi ; $k++ ) {
if ( $i > $mid ) {
$aref->[$k] = $auxref->[$j];
$j++;
}
elsif ( $j > $hi ) {
$aref->[$k] = $auxref->[$i];
$i++;
}
elsif ( $auxref->[$i] <= $auxref->[$j] ) {
$aref->[$k] = $auxref->[$i];
$i++;
}
else {
$aref->[$k] = $auxref->[$j];
$j++;
}
}
}
使用严格;
使用警告;
我的(@aref,@auxref)=();
我的($hi,$lo,$i,$j,$k,$n)=0;
@aref=(5,7,6,3,4,1,8,9,4);
$n=@aref;
合并排序(\@aref,\@auxref,0,$n-1);
打印“@auxref\n”;
打印“@aref\n”;
子合并排序{
my($aref)=$\u0;
my($auxref)=$\u1;
my$lo=$[2];
我的$hi=$[3];
如果($hi[$i];
}
$i=$lo;
$j=$mid+1;
对于($k=$lo;$k$mid){
$aref->[$k]=$auxref->[$j];
$j++;
}
elsif($j>$hi){
$aref->[$k]=$auxref->[$i];
$i++;
}
elsif($auxref->[$i][$j]){
$aref->[$k]=$auxref->[$i];
$i++;
}
否则{
$aref->[$k]=$auxref->[$j];
$j++;
}
}
}
在子合并
中,有两个数组引用:$auxref
和$aref
您正在访问数组元素,就像它们是普通数组一样(即,$aref[0]
),但由于它们是数组引用,您需要首先用箭头解除引用:$aref->[0]
将use strict;
和use warnings;
添加到脚本顶部应该可以消除这些错误
阵列
数组引用
数组引用的二维数组
数组引用的2D arrayref
阵列的二维阵列
…无法存在,因为数组只能包含标量
my @arr = ((1, 2), (3, 4));
# @arr = (1, 2, 3, 4);
下面是一个完全不依赖引用的版本。几乎可以肯定,它的内存效率不如某些原始合并排序算法预期的那样高,但它完成了任务
use strict;
use warnings;
my @array = ( 5, 7, 6, 3, 4, 1, 8, 9, 4 );
my @sorted = mergeSort(@array);
print "@sorted\n";
sub mergeSort {
my @array = @_;
if (@array > 1) {
my $mid = int(@array / 2);
my @lowArray = mergeSort(@array[0..$mid-1]);
my @highArray = mergeSort(@array[$mid..$#array]);
# Merge the two halves
my @newArray = ();
while (@lowArray && @highArray) {
if ($lowArray[0] < $highArray[0]) {
push @newArray, shift @lowArray;
} else {
push @newArray, shift @highArray;
}
}
# Either the low or high array will be empty at this point,
# so no need to compare for the remainder.
return (@newArray, @lowArray, @highArray);
} else {
return @array;
}
}
使用严格;
使用警告;
my@array=(5,7,6,3,4,1,8,9,4);
my@sorted=mergeSort(@array);
打印“@sorted\n”;
子合并排序{
我的@array=@;
如果(@array>1){
我的$mid=int(@array/2);
my@lowArray=mergeSort(@array[0..$mid-1]);
my@highArray=mergeSort(@array[$mid..$#array]);
#合并两半
我的@newArray=();
而(@lowArray&&@highArray){
如果($lowArray[0]<$highArray[0]){
推@newArray,移位@lowArray;
}否则{
按@newArray,shift@highArray;
}
}
#此时,低位或高位数组将为空,
#因此,无需对其余部分进行比较。
返回(@newArray、@lowArray、@highArray);
}否则{
返回@array;
}
}
您仍然有$auxref[$i]=$aref[$i]
在您的merge
sub中。因此,这实际上指的是您在第4行定义的数组,而不是您在merge sub开头声明的数组引用。您的数组引用现在很好。但是,与作用域相关的另一个问题是:您的sub所在的全局范围中有很多变量(意外地?)使用。例如,merge
和mergeSort
都使用了$mid
,我认为这会导致意外的结果。这就是为什么将subs放在“main”代码之前和/或放在“main”之前的原因在卷发中编码。查看mergeSort
,调用mergeSort
后使用$mid
,希望它与调用mergeSort
前具有相同的值。它没有。将$mid
的声明移动到它所属的位置。my($hi,$lo,$mid,$i,$j,$k)=0;
应该删除。其中一些变量从未使用过,而其他变量声明在错误的位置。此外,我们不必提及Perl内置的sort
自5.7以来一直是一种合并排序……可以使用使用sort'\u mergesort';
重新执行“以下是一个完全不依赖引用的合并排序版本“,你不需要为每一级递归复制整个数组来避免处理引用。这是一件坏事,不是好事。你不应该为此感到骄傲。我的反对票不仅是因为这一点,而是因为没有真正帮助OP。他在努力学习;他不是在寻找实现。”(否则他只会使用内置的排序
)@ikegami不必要地复制整个数组正是我发布这个版本的原因。它展示了一种实现他想要的东西的完美方式(这样他就可以学习),但没有提供最有可能的最终解决方案,该解决方案可能应该更严格地遵循算法。在开始语义游戏之前,您应该重新阅读我所说的“您不必要地复制每个递归级别的整个数组,以避免处理引用。”最后一部分是关键。避免使用基本工具,因为它们会给您带来问题,这不是一个好的学习方法。再说一遍,也不是简单地给出一个现有的实现,而不做任何解释。再多的文字游戏也无法改变这一点。
my @arr = ([1, 2], [3, 4]);
print $arr[0][1]; # identical to $arr[0]->[1];
push @{$arr[1]}, 5;
# @arr = ([1, 2], [3, 4, 5]);
my $arr = [[1, 2], [3, 4]];
print $arr->[0][1]; # identical to $arr->[0]->[1];
push @{$arr->[1]}, 5;
# $arr = [[1, 2], [3, 4, 5]];
my @arr = ((1, 2), (3, 4));
# @arr = (1, 2, 3, 4);
use strict;
use warnings;
my @array = ( 5, 7, 6, 3, 4, 1, 8, 9, 4 );
my @sorted = mergeSort(@array);
print "@sorted\n";
sub mergeSort {
my @array = @_;
if (@array > 1) {
my $mid = int(@array / 2);
my @lowArray = mergeSort(@array[0..$mid-1]);
my @highArray = mergeSort(@array[$mid..$#array]);
# Merge the two halves
my @newArray = ();
while (@lowArray && @highArray) {
if ($lowArray[0] < $highArray[0]) {
push @newArray, shift @lowArray;
} else {
push @newArray, shift @highArray;
}
}
# Either the low or high array will be empty at this point,
# so no need to compare for the remainder.
return (@newArray, @lowArray, @highArray);
} else {
return @array;
}
}