Na samym początku będziemy potrzebować funkcje, która będzie łączyła lewą i prawą stronę tablicy. Te części są posortowane.
function Merge { param([array]$A, [array]$temp=@(), [int]$low=0, [int]$high=$($A.Length-1), [int]$middle = $([math]::Floor($low + ($high - $low)/2)) ) $i = $low $j = $middle +1 Assert-Command {IsSorted ($A[$i..$middle]) } Assert-Command {IsSorted ($A[$j..$high]) } $temp = $A $swapA = @(0)* $A.Length for($k = $low; $k -le $high; $k++) { if( $i -gt $middle) { $swapA[$k] = $temp[$j] $j++ } elseif ($j -gt $high) { $swapA[$k] = $temp[$i] $i++ } elseif( $temp[$j] -gt $temp[$i] ) { $swapA[$k] = $temp[$i] $i++ } else { $swapA[$k] = $temp[$j] $j++ } } $sortedA =$swapA[$low..$high] Assert-Command {IsSorted $sortedA} return $sortedA }Napiszemy prostą funkcję do sprawdzenia czy elementy są posortowane:
function IsSorted([array]$arr) { for($i=0; $i -lt $arr.Length-1; $i++) { if($arr[$i] -gt $arr[$i+1]) { return $false } } return $true }
Do funkcji scalania potrzebna jest funkcja asercji:
function Assert-Command { param( [Parameter(Position=0,Mandatory=$true)] [ScriptBlock]$condition, [Parameter(Position=1)] [string]$message ) $invoke = $MyInvocation try{ $ErrorActionPreference = "STOP" $result = &$condition }catch{ $result=$false $exceptionType = $_.Exception.GetType().FullName } if(-not($result)) { $errMess = "Assert failed in line: $($invoke.Line) `n" $errMess += "Message: $message `n" $errMess += "Exception type: $exceptionType `n" $errMess += "Used parameters: $($invoke.BoundParameters.condition) `n" throw $errMess } }I na końcu potrzebujemy funkcji sortując:
function MergeSort-Object { param([array]$A, [array]$temp=@(), [int]$low=0, [int]$high=$($A.Length-1), [int]$middle = $([math]::Floor($low + ($high - $low)/2)) ) if($low -ge $high) { return $A[$low] } [array]$sortedPart1 = MergeSort-Object -A $A -low $low -high $middle $A = Fill-Array -table $A -with $sortedPart1 -offSet $low [array]$sortedPart2 = MergeSort-Object -A $A -low ($middle+1) -high $high $A = Fill-Array -table $A -with $sortedPart2 -offSet ($middle+1) [array]$sorted = Merge -A $A -low $low -middle $middle -high $high return $sorted }Niestety będziemy musieli użyć pomocniczej funkcji do wypełnienia tablicy już posortowanej części. Są to uroki przekazywania parametrów funkcji przez wartość, a nie przez referencje.
function Fill-Array { param([array]$table, [int]$offSet=0, [array]$with ) [array]$newTable = $table for($i =0; $i -lt $with.Length; $i++) { $newTable[$offSet + $i] = $with[$i] } return $newTable }I przykładowe sortowanie tablicy wygląda następująco:
MergeSort-Object -A 1,3,7,99,5,3,32,5,11,91
Brak komentarzy:
Prześlij komentarz