Skip to content

Commit 54c81cf

Browse files
authored
Merge pull request #6 from KaririCode-Framework/develop
feat: Refactor ArrayQueue, Create CircularArrayQueue, Refactor ArrayD…
2 parents 0f45efa + edce0d7 commit 54c81cf

File tree

6 files changed

+203
-140
lines changed

6 files changed

+203
-140
lines changed

composer.lock

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Queue/ArrayDeque.php

Lines changed: 3 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace KaririCode\DataStructure\Queue;
66

7+
use KaririCode\Contract\DataStructure\Deque;
78
use KaririCode\Contract\DataStructure\Queue;
89

910
/**
@@ -16,45 +17,9 @@
1617
*
1718
* @implements Queue<mixed>
1819
*/
19-
class ArrayDeque implements Queue
20-
{
21-
private array $elements;
22-
private int $front = 0;
23-
private int $size = 0;
24-
private int $capacity;
25-
26-
public function __construct(int $initialCapacity = 16)
27-
{
28-
$this->capacity = $initialCapacity;
29-
$this->elements = array_fill(0, $this->capacity, null);
30-
}
31-
32-
public function enqueue(mixed $element): void
33-
{
34-
$this->ensureCapacity();
35-
$index = ($this->front + $this->size) % $this->capacity;
36-
$this->elements[$index] = $element;
37-
++$this->size;
38-
}
39-
40-
public function dequeue(): mixed
41-
{
42-
if ($this->isEmpty()) {
43-
return null;
44-
}
45-
$element = $this->elements[$this->front];
46-
$this->elements[$this->front] = null;
47-
$this->front = ($this->front + 1) % $this->capacity;
48-
--$this->size;
49-
50-
return $element;
51-
}
52-
53-
public function peek(): mixed
54-
{
55-
return $this->isEmpty() ? null : $this->elements[$this->front];
56-
}
5720

21+
class ArrayDeque extends CircularArrayQueue implements Deque
22+
{
5823
public function addFirst(mixed $element): void
5924
{
6025
$this->ensureCapacity();
@@ -85,31 +50,4 @@ public function peekLast(): mixed
8550

8651
return $this->elements[$index];
8752
}
88-
89-
public function isEmpty(): bool
90-
{
91-
return 0 === $this->size;
92-
}
93-
94-
public function size(): int
95-
{
96-
return $this->size;
97-
}
98-
99-
/**
100-
* Ensures that the deque has enough capacity to add a new element.
101-
*/
102-
private function ensureCapacity(): void
103-
{
104-
if ($this->size === $this->capacity) {
105-
$newCapacity = $this->capacity * 2;
106-
$newElements = array_fill(0, $newCapacity, null);
107-
for ($i = 0; $i < $this->size; ++$i) {
108-
$newElements[$i] = $this->elements[($this->front + $i) % $this->capacity];
109-
}
110-
$this->elements = $newElements;
111-
$this->front = 0;
112-
$this->capacity = $newCapacity;
113-
}
114-
}
11553
}

src/Queue/ArrayQueue.php

Lines changed: 3 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -19,69 +19,8 @@
1919
*
2020
* @see https://kariricode.org/
2121
*/
22-
class ArrayQueue implements Queue
23-
{
24-
private array $elements;
25-
private int $front = 0;
26-
private int $size = 0;
27-
private int $capacity;
28-
29-
public function __construct(int $initialCapacity = 16)
30-
{
31-
$this->capacity = $initialCapacity;
32-
$this->elements = array_fill(0, $this->capacity, null);
33-
}
34-
35-
public function enqueue(mixed $element): void
36-
{
37-
$this->ensureCapacity();
38-
$index = ($this->front + $this->size) % $this->capacity;
39-
$this->elements[$index] = $element;
40-
++$this->size;
41-
}
42-
43-
public function dequeue(): mixed
44-
{
45-
if ($this->isEmpty()) {
46-
return null;
47-
}
48-
$element = $this->elements[$this->front];
49-
$this->elements[$this->front] = null;
50-
$this->front = ($this->front + 1) % $this->capacity;
51-
--$this->size;
52-
53-
return $element;
54-
}
5522

56-
public function peek(): mixed
57-
{
58-
return $this->isEmpty() ? null : $this->elements[$this->front];
59-
}
60-
61-
public function isEmpty(): bool
62-
{
63-
return 0 === $this->size;
64-
}
65-
66-
public function size(): int
67-
{
68-
return $this->size;
69-
}
70-
71-
/**
72-
* Ensures that the queue has enough capacity to add a new element.
73-
*/
74-
private function ensureCapacity(): void
75-
{
76-
if ($this->size === $this->capacity) {
77-
$newCapacity = $this->capacity * 2;
78-
$newElements = array_fill(0, $newCapacity, null);
79-
for ($i = 0; $i < $this->size; ++$i) {
80-
$newElements[$i] = $this->elements[($this->front + $i) % $this->capacity];
81-
}
82-
$this->elements = $newElements;
83-
$this->front = 0;
84-
$this->capacity = $newCapacity;
85-
}
86-
}
23+
class ArrayQueue extends CircularArrayQueue implements Queue
24+
{
25+
// No additional methods required, uses methods from CircularArrayQueue
8726
}

src/Queue/CircularArrayQueue.php

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\DataStructure\Queue;
6+
7+
use KaririCode\Contract\DataStructure\Queue;
8+
9+
/**
10+
* CircularArrayQueue implementation.
11+
*
12+
* This class provides the common functionality for array-based queues using a circular array.
13+
*
14+
* @category Queues
15+
*
16+
* @author Walmir Silva <walmir.silva@kariricode.org>
17+
* @license MIT
18+
*
19+
* @see https://kariricode.org/
20+
*/
21+
abstract class CircularArrayQueue implements Queue
22+
{
23+
protected array $elements;
24+
protected int $front = 0;
25+
protected int $size = 0;
26+
protected int $capacity;
27+
28+
public function __construct(int $initialCapacity = 16)
29+
{
30+
$this->capacity = $initialCapacity;
31+
$this->elements = array_fill(0, $this->capacity, null);
32+
}
33+
34+
public function isEmpty(): bool
35+
{
36+
return $this->size === 0;
37+
}
38+
39+
public function size(): int
40+
{
41+
return $this->size;
42+
}
43+
44+
public function clear(): void
45+
{
46+
$this->elements = array_fill(0, $this->capacity, null);
47+
$this->front = 0;
48+
$this->size = 0;
49+
}
50+
51+
protected function ensureCapacity(): void
52+
{
53+
if ($this->size === $this->capacity) {
54+
$newCapacity = $this->capacity * 2;
55+
$newElements = array_fill(0, $newCapacity, null);
56+
for ($i = 0; $i < $this->size; ++$i) {
57+
$newElements[$i] = $this->elements[($this->front + $i) % $this->capacity];
58+
}
59+
$this->elements = $newElements;
60+
$this->front = 0;
61+
$this->capacity = $newCapacity;
62+
}
63+
}
64+
65+
public function peek(): mixed
66+
{
67+
return $this->isEmpty() ? null : $this->elements[$this->front];
68+
}
69+
70+
public function dequeue(): mixed
71+
{
72+
if ($this->isEmpty()) {
73+
return null;
74+
}
75+
$element = $this->elements[$this->front];
76+
$this->elements[$this->front] = null;
77+
$this->front = ($this->front + 1) % $this->capacity;
78+
--$this->size;
79+
80+
return $element;
81+
}
82+
83+
public function enqueue(mixed $element): void
84+
{
85+
$this->ensureCapacity();
86+
$index = ($this->front + $this->size) % $this->capacity;
87+
$this->elements[$index] = $element;
88+
++$this->size;
89+
}
90+
91+
public function getItems(): array
92+
{
93+
$items = [];
94+
for ($i = 0; $i < $this->size; ++$i) {
95+
$items[] = $this->elements[($this->front + $i) % $this->capacity];
96+
}
97+
return $items;
98+
}
99+
}

tests/Queue/ArrayDequeTest.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,69 @@ public function testDequeBehaviorAfterMixedOperations(): void
172172
$this->assertSame(1, $deque->dequeue());
173173
$this->assertSame(3, $deque->peekLast());
174174
}
175+
176+
// Test capacity expansion during addFirst operations
177+
public function testEnsureCapacityExpandsDuringAddFirstOperations(): void
178+
{
179+
$deque = new ArrayDeque(2);
180+
$deque->addFirst(1);
181+
$deque->addFirst(2);
182+
$deque->addFirst(3); // Should trigger capacity increase
183+
$this->assertSame(3, $deque->size());
184+
$this->assertSame(3, $deque->peek());
185+
$this->assertSame(1, $deque->peekLast());
186+
}
187+
188+
// Test capacity expansion during removeLast operations
189+
public function testEnsureCapacityExpandsDuringRemoveLastOperations(): void
190+
{
191+
$deque = new ArrayDeque(2);
192+
$deque->enqueue(1);
193+
$deque->enqueue(2);
194+
$deque->enqueue(3); // Should trigger capacity increase
195+
$deque->removeLast();
196+
$deque->removeLast();
197+
$this->assertSame(1, $deque->size());
198+
$this->assertSame(1, $deque->peek());
199+
}
200+
201+
// Test mixed operations of addFirst, addLast, removeFirst, and removeLast
202+
public function testMixedOperations(): void
203+
{
204+
$deque = new ArrayDeque();
205+
$deque->addFirst(1);
206+
$deque->enqueue(2);
207+
$deque->addFirst(0);
208+
$this->assertSame(0, $deque->dequeue());
209+
$this->assertSame(1, $deque->dequeue());
210+
$this->assertSame(2, $deque->removeLast());
211+
$deque->enqueue(3);
212+
$deque->addFirst(4);
213+
$this->assertSame(4, $deque->peek());
214+
$this->assertSame(3, $deque->peekLast());
215+
}
216+
217+
// Test clearing the deque
218+
public function testClearEmptiesTheDeque(): void
219+
{
220+
$deque = new ArrayDeque();
221+
$deque->enqueue(1);
222+
$deque->enqueue(2);
223+
$deque->clear();
224+
$this->assertTrue($deque->isEmpty());
225+
$this->assertNull($deque->peek());
226+
$this->assertNull($deque->peekLast());
227+
$this->assertNull($deque->dequeue());
228+
$this->assertNull($deque->removeLast());
229+
}
230+
231+
// Test getting all items
232+
public function testGetItemsReturnsAllElementsInCorrectOrder(): void
233+
{
234+
$deque = new ArrayDeque();
235+
$deque->enqueue(1);
236+
$deque->enqueue(2);
237+
$deque->enqueue(3);
238+
$this->assertSame([1, 2, 3], $deque->getItems());
239+
}
175240
}

0 commit comments

Comments
 (0)