mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-02-07 13:08:40 +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);
|
$n = \count($list);
|
||||||
|
|
||||||
|
if ($n < 2) {
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$newN = 0;
|
$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;
|
$start = 0;
|
||||||
$end = \count($list) - 1;
|
$end = \count($list) - 1;
|
||||||
|
|
||||||
|
if ($end < 1) {
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
while ($start <= $end) {
|
while ($start <= $end) {
|
||||||
$newStart = $end;
|
$newStart = $end;
|
||||||
$newEnd = $start;
|
$newEnd = $start;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,10 @@ class CombSort implements SortInterface
|
||||||
$gap = $n;
|
$gap = $n;
|
||||||
$shrink = 1.3;
|
$shrink = 1.3;
|
||||||
|
|
||||||
|
if ($n < 2) {
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
while (!$sorted) {
|
while (!$sorted) {
|
||||||
$gap = (int) \floor($gap / $shrink);
|
$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);
|
$n = \count($list);
|
||||||
|
|
||||||
|
if ($n < 2) {
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
for ($i = 1; $i < $n; ++$i) {
|
for ($i = 1; $i < $n; ++$i) {
|
||||||
$j = $i;
|
$j = $i;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@ class OddEvenSort implements SortInterface
|
||||||
$sorted = false;
|
$sorted = false;
|
||||||
$n = \count($list);
|
$n = \count($list);
|
||||||
|
|
||||||
|
if ($n < 2) {
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
while (!$sorted) {
|
while (!$sorted) {
|
||||||
$sorted = true;
|
$sorted = true;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,10 @@ class SelectionSort implements SortInterface
|
||||||
{
|
{
|
||||||
$n = \count($list);
|
$n = \count($list);
|
||||||
|
|
||||||
|
if ($n < 2) {
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
for ($i = 0; $i < $n - 1; ++$i) {
|
for ($i = 0; $i < $n - 1; ++$i) {
|
||||||
$min = $i;
|
$min = $i;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,4 +25,10 @@ namespace phpOMS\Algorithm\Sort;
|
||||||
interface SortableInterface
|
interface SortableInterface
|
||||||
{
|
{
|
||||||
public function compare(self $obj, int $order = SortOrder::ASC) : bool;
|
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) {
|
for ($i = 0; $i < $nDim; ++$i) {
|
||||||
$j;
|
$j;
|
||||||
for ($j = 0; $j < $mDim; ++$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;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($j === $mDim) {
|
if ($j === $mDim) {
|
||||||
|
|
@ -321,8 +322,9 @@ class Matrix implements \ArrayAccess, \Iterator
|
||||||
|
|
||||||
for ($k = 0; $k < $mDim; ++$k) {
|
for ($k = 0; $k < $mDim; ++$k) {
|
||||||
if ($k !== $j && \abs($matrix[$k][$i]) > 0.0001) {
|
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];
|
$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;
|
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