mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-02-14 07:28:41 +00:00
Implement more sorting algorithms
This commit is contained in:
parent
7b1cf0e660
commit
047d8c3028
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.4
|
||||
*
|
||||
* @package phpOMS\Algorithm\Sort;
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\Algorithm\Sort;
|
||||
|
||||
/**
|
||||
* BitonicSort class.
|
||||
*
|
||||
* @package phpOMS\Algorithm\Sort;
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class BitonicSort implements SortInterface
|
||||
{
|
||||
public static function sort(array $list, int $order = SortOrder::ASC) : array
|
||||
{
|
||||
$n = \count($list);
|
||||
|
||||
if ($n < 2) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
$first = self::sort(\array_slice($list, 0, $n / 2), SortOrder::ASC);
|
||||
$second = self::sort(\array_slice($list, $n / 2), SortOrder::DESC);
|
||||
|
||||
return self::merge(\array_merge($first, $second), $order);
|
||||
}
|
||||
|
||||
public static function merge(array $list, int $order) : array
|
||||
{
|
||||
$n = \count($list);
|
||||
|
||||
if ($n === 1) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
$dist = $n / 2;
|
||||
for ($i = 0; $i < $dist; ++$i) {
|
||||
if ($list[$i]->compare($list[$i + $dist], $order)) {
|
||||
$old = $list[$i];
|
||||
$list[$i] = $list[$i + $dist];
|
||||
$list[$i + $dist] = $old;
|
||||
}
|
||||
}
|
||||
|
||||
$first = self::merge(\array_slice($list, 0, $n / 2), $order);
|
||||
$second = self::merge(\array_slice($list, $n / 2), $order);
|
||||
|
||||
return \array_merge($first, $second);
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,10 @@ class BubbleSort implements SortInterface
|
|||
{
|
||||
$n = \count($list);
|
||||
|
||||
if ($n < 2) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
do {
|
||||
$newN = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.4
|
||||
*
|
||||
* @package phpOMS\Algorithm\Sort;
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\Algorithm\Sort;
|
||||
|
||||
/**
|
||||
* Bucketsort class.
|
||||
*
|
||||
* @package phpOMS\Algorithm\Sort;
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class BucketSort
|
||||
{
|
||||
public static function sort(array $list, int $bucketCount, string $algo = InsertionSort::class, int $order = SortOrder::ASC) : array
|
||||
{
|
||||
$buckets = [];
|
||||
$M = $list[0]::max($list);
|
||||
|
||||
foreach ($list as $element) {
|
||||
$buckets[(int) \floor(($bucketCount - 1) * $element->getValue() / $M)][] = $element;
|
||||
}
|
||||
|
||||
$sorted = [];
|
||||
foreach ($buckets as $bucket) {
|
||||
$sorted[] = $algo::sort($bucket, SortOrder::ASC);
|
||||
}
|
||||
|
||||
return $order === SortOrder::ASC ? \array_merge(...$sorted) : \array_reverse(\array_merge(...$sorted), false);
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,10 @@ class CocktailShakerSort implements SortInterface
|
|||
$start = 0;
|
||||
$end = \count($list) - 1;
|
||||
|
||||
if ($end < 1) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
while ($start <= $end) {
|
||||
$newStart = $end;
|
||||
$newEnd = $start;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ class CombSort implements SortInterface
|
|||
$gap = $n;
|
||||
$shrink = 1.3;
|
||||
|
||||
if ($n < 2) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
while (!$sorted) {
|
||||
$gap = (int) \floor($gap / $shrink);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.4
|
||||
*
|
||||
* @package phpOMS\Algorithm\Sort;
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\Algorithm\Sort;
|
||||
|
||||
/**
|
||||
* CycleSort class.
|
||||
*
|
||||
* @package phpOMS\Algorithm\Sort;
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class CycleSort implements SortInterface
|
||||
{
|
||||
public static function sort(array $list, int $order = SortOrder::ASC) : array
|
||||
{
|
||||
$writes = 0;
|
||||
$n = \count($list);
|
||||
|
||||
if ($n < 2) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
for ($start = 0; $start < \count($list) - 1; ++$start) {
|
||||
$item = $list[$start];
|
||||
|
||||
$pos = $start;
|
||||
$length0 = \count($list);
|
||||
for ($i = $start + 1; $i < $length0; ++$i) {
|
||||
if ($list[$i]->getValue() < $item->getValue()) {
|
||||
++$pos;
|
||||
}
|
||||
}
|
||||
|
||||
if ($pos === $start) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while ($item->getValue() === $list[$pos]->getValue()) {
|
||||
++$pos;
|
||||
}
|
||||
|
||||
$old = $list[$pos];
|
||||
$list[$pos] = $item;
|
||||
$item = $old;
|
||||
++$writes;
|
||||
|
||||
while ($pos !== $start) {
|
||||
$pos = $start;
|
||||
$length1 = \count($list);
|
||||
for ($i = $start + 1; $i < $length1; ++$i) {
|
||||
if ($list[$i]->getValue() < $item->getValue()) {
|
||||
++$pos;
|
||||
}
|
||||
}
|
||||
|
||||
while ($item->getValue() === $list[$pos]->getValue()) {
|
||||
++$pos;
|
||||
}
|
||||
|
||||
$old = $list[$pos];
|
||||
$list[$pos] = $item;
|
||||
$item = $old;
|
||||
++$writes;
|
||||
}
|
||||
}
|
||||
|
||||
return $order === SortOrder::ASC ? $list : \array_reverse($list, false);;
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,10 @@ class GnomeSort implements SortInterface
|
|||
{
|
||||
$n = \count($list);
|
||||
|
||||
if ($n < 2) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
for ($i = 1; $i < $n; ++$i) {
|
||||
$j = $i;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ class OddEvenSort implements SortInterface
|
|||
$sorted = false;
|
||||
$n = \count($list);
|
||||
|
||||
if ($n < 2) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
while (!$sorted) {
|
||||
$sorted = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ class SelectionSort implements SortInterface
|
|||
{
|
||||
$n = \count($list);
|
||||
|
||||
if ($n < 2) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $n - 1; ++$i) {
|
||||
$min = $i;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,4 +25,10 @@ namespace phpOMS\Algorithm\Sort;
|
|||
interface SortableInterface
|
||||
{
|
||||
public function compare(self $obj, int $order = SortOrder::ASC) : bool;
|
||||
|
||||
public function getValue();
|
||||
|
||||
public static function max(array $list);
|
||||
|
||||
public static function min(array $list);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -307,8 +307,9 @@ class Matrix implements \ArrayAccess, \Iterator
|
|||
for ($i = 0; $i < $nDim; ++$i) {
|
||||
$j;
|
||||
for ($j = 0; $j < $mDim; ++$j) {
|
||||
if (!$selected[$j] && \abs($matrix[$j][$i]) > 0.0001)
|
||||
if (!$selected[$j] && \abs($matrix[$j][$i]) > 0.0001) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($j === $mDim) {
|
||||
|
|
@ -321,8 +322,9 @@ class Matrix implements \ArrayAccess, \Iterator
|
|||
|
||||
for ($k = 0; $k < $mDim; ++$k) {
|
||||
if ($k !== $j && \abs($matrix[$k][$i]) > 0.0001) {
|
||||
for ($p = $i + 1; $p < $nDim; ++$p)
|
||||
for ($p = $i + 1; $p < $nDim; ++$p) {
|
||||
$matrix[$k][$p] -= $matrix[$j][$p] * $matrix[$k][$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
56
tests/Algorithm/Sort/BitonicSortTest.php
Normal file
56
tests/Algorithm/Sort/BitonicSortTest.php
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.4
|
||||
*
|
||||
* @package tests
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\tests\Algorithm\Sort;
|
||||
|
||||
use phpOMS\Algorithm\Sort\BitonicSort;
|
||||
use phpOMS\Algorithm\Sort\SortOrder;
|
||||
|
||||
require_once __DIR__ . '/../../Autoloader.php';
|
||||
|
||||
/**
|
||||
* @testdox phpOMS\tests\Algorithm\Sort: Bitonic sort test
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class BitonicSortTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected $list = [];
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->list = [
|
||||
new NumericElement(5),
|
||||
new NumericElement(1),
|
||||
new NumericElement(4),
|
||||
new NumericElement(2),
|
||||
];
|
||||
}
|
||||
|
||||
public function testSortASC() : void
|
||||
{
|
||||
$newList = BitonicSort::sort($this->list);
|
||||
self::assertEquals(
|
||||
[1, 2, 4, 5], [$newList[0]->value, $newList[1]->value, $newList[2]->value, $newList[3]->value]
|
||||
);
|
||||
}
|
||||
|
||||
public function testSortDESC() : void
|
||||
{
|
||||
$newList = BitonicSort::sort($this->list, SortOrder::DESC);
|
||||
self::assertEquals(
|
||||
[5, 4, 2, 1], [$newList[0]->value, $newList[1]->value, $newList[2]->value, $newList[3]->value]
|
||||
);
|
||||
}
|
||||
}
|
||||
57
tests/Algorithm/Sort/BucketSortTest.php
Normal file
57
tests/Algorithm/Sort/BucketSortTest.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.4
|
||||
*
|
||||
* @package tests
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\tests\Algorithm\Sort;
|
||||
|
||||
use phpOMS\Algorithm\Sort\BucketSort;
|
||||
use phpOMS\Algorithm\Sort\SortOrder;
|
||||
|
||||
require_once __DIR__ . '/../../Autoloader.php';
|
||||
|
||||
/**
|
||||
* @testdox phpOMS\tests\Algorithm\Sort: Bucket sort test
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class BucketSortTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected $list = [];
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->list = [
|
||||
new NumericElement(5),
|
||||
new NumericElement(1),
|
||||
new NumericElement(4),
|
||||
new NumericElement(2),
|
||||
new NumericElement(8),
|
||||
];
|
||||
}
|
||||
|
||||
public function testSortASC() : void
|
||||
{
|
||||
$newList = BucketSort::sort($this->list, 2, \phpOMS\Algorithm\Sort\SelectionSort::class);
|
||||
self::assertEquals(
|
||||
[1, 2, 4, 5, 8], [$newList[0]->value, $newList[1]->value, $newList[2]->value, $newList[3]->value, $newList[4]->value,]
|
||||
);
|
||||
}
|
||||
|
||||
public function testSortDESC() : void
|
||||
{
|
||||
$newList = BucketSort::sort($this->list, 2, \phpOMS\Algorithm\Sort\SelectionSort::class, SortOrder::DESC);
|
||||
self::assertEquals(
|
||||
[8, 5, 4, 2, 1], [$newList[0]->value, $newList[1]->value, $newList[2]->value, $newList[3]->value, $newList[4]->value,]
|
||||
);
|
||||
}
|
||||
}
|
||||
57
tests/Algorithm/Sort/CycleSortTest.php
Normal file
57
tests/Algorithm/Sort/CycleSortTest.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.4
|
||||
*
|
||||
* @package tests
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\tests\Algorithm\Sort;
|
||||
|
||||
use phpOMS\Algorithm\Sort\CycleSort;
|
||||
use phpOMS\Algorithm\Sort\SortOrder;
|
||||
|
||||
require_once __DIR__ . '/../../Autoloader.php';
|
||||
|
||||
/**
|
||||
* @testdox phpOMS\tests\Algorithm\Sort: Cycle sort test
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class CycleSortTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected $list = [];
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->list = [
|
||||
new NumericElement(5),
|
||||
new NumericElement(1),
|
||||
new NumericElement(4),
|
||||
new NumericElement(2),
|
||||
new NumericElement(8),
|
||||
];
|
||||
}
|
||||
|
||||
public function testSortASC() : void
|
||||
{
|
||||
$newList = CycleSort::sort($this->list);
|
||||
self::assertEquals(
|
||||
[1, 2, 4, 5, 8], [$newList[0]->value, $newList[1]->value, $newList[2]->value, $newList[3]->value, $newList[4]->value,]
|
||||
);
|
||||
}
|
||||
|
||||
public function testSortDESC() : void
|
||||
{
|
||||
$newList = CycleSort::sort($this->list, SortOrder::DESC);
|
||||
self::assertEquals(
|
||||
[8, 5, 4, 2, 1], [$newList[0]->value, $newList[1]->value, $newList[2]->value, $newList[3]->value, $newList[4]->value,]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -32,4 +32,29 @@ class NumericElement implements SortableInterface
|
|||
{
|
||||
return $order === SortOrder::ASC ? $this->value > $obj->value : $this->value < $obj->value;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public static function max(array $list)
|
||||
{
|
||||
$values = [];
|
||||
foreach ($list as $element) {
|
||||
$values[] = $element->value;
|
||||
}
|
||||
|
||||
return \max($values);
|
||||
}
|
||||
|
||||
public static function min(array $list)
|
||||
{
|
||||
$values = [];
|
||||
foreach ($list as $element) {
|
||||
$values[] = $element->value;
|
||||
}
|
||||
|
||||
return \min($values);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user