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