diff --git a/README.md b/README.md index ec73541..a09ae65 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,4 @@ ## Sort * Bubble Sort +* Quick Sort \ No newline at end of file diff --git a/src/Sort/Quick.php b/src/Sort/Quick.php new file mode 100644 index 0000000..d317026 --- /dev/null +++ b/src/Sort/Quick.php @@ -0,0 +1,92 @@ +sortRecursive($items, 0, count($items) - 1, $items[array_rand($items)]); + } + + private function sortRecursive(array $items, int $start, int $end, $pivot): array + { + $leftIndex = $this->searchLeft($items, $pivot, $start); + $rightIndex = $this->searchRight($items, $pivot, $end); + + if ($leftIndex < $rightIndex) { + $items = $this->swap($items, $leftIndex, $rightIndex); + return $this->sortRecursive($items, $leftIndex + 1, $rightIndex - 1, $pivot); + } + + [$leftItems, $rightItems] = $this->slice($items, $leftIndex); + + if (count($leftItems) > 1) { + $leftItems = $this->sort($leftItems); + } + + if (count($rightItems) > 1) { + $rightItems = $this->sort($rightItems); + } + + return array_merge($leftItems, $rightItems); + } + + private function searchLeft(array $items, $pivot, int $offset): int + { + $length = count($items); + for ($index = $offset; $index < $length; $index++) { + $item = $items[$index]; + + if ($item < $pivot) { + continue; + } + + break; + } + + return $index; + } + + private function searchRight(array $items, $pivot, int $offset): int + { + for ($index = $offset; $index >= 0; $index--) { + $item = $items[$index]; + + if ($item > $pivot) { + continue; + } + + break; + } + + return $index; + } + + private function swap(array $items, int $baseIndex, int $targetIndex): array + { + $baseItem = $items[$baseIndex]; + $targetItem = $items[$targetIndex]; + $items[$baseIndex] = $targetItem; + $items[$targetIndex] = $baseItem; + return $items; + } + + private function slice(array $items, int $index): array + { + $leftItems = array_slice($items, 0, $index); + $rightItems = array_slice($items, $index); + return [$leftItems, $rightItems]; + } +} \ No newline at end of file diff --git a/tests/Sort/QuickTest.php b/tests/Sort/QuickTest.php new file mode 100644 index 0000000..94ca875 --- /dev/null +++ b/tests/Sort/QuickTest.php @@ -0,0 +1,52 @@ +quick = new Quick(); + } + + public function sortDataProvider(): array + { + return [ + 'pattern int 1' => [ + 'actual' => [4, 1, 3, 2], + 'expected' => [1, 2, 3, 4], + ], + 'pattern int 2' => [ + 'actual' => [7, 17, 5, 3, 13, 2, 11], + 'expected' => [2, 3, 5, 7, 11, 13, 17], + ], + 'pattern float 1' => [ + 'actual' => [2.4, 2.7, 0.3, 1.1, 1.0], + 'expected' => [0.3, 1.0, 1.1, 2.4, 2.7], + ], + 'pattern string 1' => [ + 'actual' => ['monster', 'drink', 'channel', 'speaker', 'towel', 'phone'], + 'expected' => ['channel', 'drink', 'monster', 'phone', 'speaker', 'towel'], + ], + ]; + } + + /** + * @dataProvider sortDataProvider + * @param array $actual + * @param array $expected + */ + public function testSort(array $actual, array $expected) + { + $this->assertEquals($expected, $this->quick->sort($actual)); + } +}