2014-02-23 3 views
0

Perl에서 병합 정렬을 구현하려고했지만 Perl을 처음 접했고 배열 참조에 문제가 있음을 알고 있습니다. 배열은 프로세스가 완료된 후에 같은 값을 유지합니다. 내가 어디로 잘못 가고 있는지 보지 못하게 해주세요.Perl mergesort - 배열 참조

수정 된 코드 : $auxref$aref :

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++; 
     } 
    } 
} 

답변

2

sub merge에서, 두 개의 배열 심판이있다.

배열 요소는 일반적인 배열 (즉, $aref[0]) 인 것처럼 액세스하지만 배열 참조이므로 화살표로 우선 참조 해제해야합니다 ($aref->[0]).

스크립트 상단에 use strict;use warnings;을 추가하면 이러한 오류가 제거됩니다.

어레이

my @arr = (1, 2, 3, 4); 
$arr[0] = 5; 
push @arr, 6; 
# @arr = (5, 2, 3, 4, 6) 

어레이 배열

my $arr = [1,2,3]; 
$arr->[0] = 5; 
push @$arr, 6; 
# $arr = [5, 2, 3, 4, 6]; 

2D 배열을 참조 참고

배열의 17,451,515,
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]); 

2D arrayref 배열의

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]]; 

2 차원 배열을 참조

... 배열은 스칼라

을 보유 할 수 있기 때문에 존재할 수 없다
my @arr = ((1, 2), (3, 4)); 
# @arr = (1, 2, 3, 4); 
+0

시도해도 여전히 작동하지 않았습니다. 위의 코드를 업데이트했습니다. – chettyharish

+0

addition ->도 도움이되지 않았다. – chettyharish

+1

'merge' 하위에'$ auxref [$ i] = $ aref [$ i]'가 남아 있습니다. 따라서 실제로 병합 서브의 시작 부분에서 선언 한 배열 참조가 아니라 4 행에서 정의한 배열을 참조합니다. – aidan

0

다음은 참조에 전혀 의존하지 않는 merge sort의 버전입니다. 원래의 병합 정렬 알고리즘 중 일부가 의도 한만큼 메모리가 효율적이지는 않지만 거의 완료되었습니다.

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; 
    } 
} 
+0

또한 우리를 속이지 않을 것입니다. Perl에 내장 된'sort'는 5.7 이후 병합 형식이었습니다. – aidan

+0

...'use sort '_mergesort'; ' – ikegami

+1

Re'를 사용하여 enforced 할 수 있습니다. 다음은 다음과 같은 병합 유형입니다. 레퍼런스를 전혀 사용하지 마십시오. "참조를 사용하지 않으려면 각 레크 리 에이션 레벨에 대한 전체 배열을 불필요하게 복사하십시오. 좋지 않은 것이지 나쁜 것이지요. 당신이 자랑스러워해서는 안됩니다. 내 downvote는 단지 그것을위한 것이 아닙니다. 그는 실제로 OP를 돕지 않기 때문에 그는 배움을 시도하고 구현을 찾고 있지 않습니다. (아니면 그냥 내장 된 '정렬'을 사용하는 것입니다.) – ikegami