Skip to content

Commit 0f45efa

Browse files
authored
Merge pull request #5 from KaririCode-Framework/develop
Add ArrayStack Implementation and Comprehensive Unit Tests
2 parents 97d93b2 + 78f10fa commit 0f45efa

File tree

2 files changed

+202
-0
lines changed

2 files changed

+202
-0
lines changed

src/Stack/ArrayStack.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\DataStructure\Stack;
6+
7+
use KaririCode\Contract\DataStructure\Stack;
8+
9+
/**
10+
* ArrayStack implementation.
11+
*
12+
* This class implements a stack using a dynamic array.
13+
* It provides O(1) time complexity for push, pop, and peek operations.
14+
*
15+
* @category Stacks
16+
*
17+
* @author Walmir Silva <walmir.silva@kariricode.org>
18+
* @license MIT
19+
*
20+
* @see https://kariricode.org/
21+
*/
22+
class ArrayStack implements Stack
23+
{
24+
private array $elements = [];
25+
26+
public function push(mixed $element): void
27+
{
28+
$this->elements[] = $element;
29+
}
30+
31+
public function pop(): mixed
32+
{
33+
if ($this->isEmpty()) {
34+
return null;
35+
}
36+
37+
return array_pop($this->elements);
38+
}
39+
40+
public function peek(): mixed
41+
{
42+
if ($this->isEmpty()) {
43+
return null;
44+
}
45+
46+
return $this->elements[count($this->elements) - 1];
47+
}
48+
49+
public function isEmpty(): bool
50+
{
51+
return empty($this->elements);
52+
}
53+
54+
public function size(): int
55+
{
56+
return count($this->elements);
57+
}
58+
59+
public function clear(): void
60+
{
61+
$this->elements = [];
62+
}
63+
64+
public function getItems(): array
65+
{
66+
return array_reverse($this->elements);
67+
}
68+
}

tests/Stack/ArrayStackTest.php

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\DataStructure\Tests\Stack;
6+
7+
use KaririCode\DataStructure\Stack\ArrayStack;
8+
use PHPUnit\Framework\TestCase;
9+
10+
final class ArrayStackTest extends TestCase
11+
{
12+
// Test pushing elements onto the stack
13+
public function testPushAddsElementToStack(): void
14+
{
15+
$stack = new ArrayStack();
16+
$stack->push(1);
17+
$this->assertSame(1, $stack->peek());
18+
}
19+
20+
// Test popping elements from the stack
21+
public function testPopRemovesElementFromStack(): void
22+
{
23+
$stack = new ArrayStack();
24+
$stack->push(1);
25+
$stack->push(2);
26+
$this->assertSame(2, $stack->pop());
27+
$this->assertSame(1, $stack->peek());
28+
}
29+
30+
// Test popping from an empty stack
31+
public function testPopFromEmptyStackReturnsNull(): void
32+
{
33+
$stack = new ArrayStack();
34+
$this->assertNull($stack->pop());
35+
}
36+
37+
// Test peeking elements
38+
public function testPeekReturnsElementFromTopWithoutRemovingIt(): void
39+
{
40+
$stack = new ArrayStack();
41+
$stack->push(1);
42+
$this->assertSame(1, $stack->peek());
43+
$this->assertSame(1, $stack->peek());
44+
}
45+
46+
// Test peeking from an empty stack
47+
public function testPeekFromEmptyStackReturnsNull(): void
48+
{
49+
$stack = new ArrayStack();
50+
$this->assertNull($stack->peek());
51+
}
52+
53+
// Test checking if stack is empty
54+
public function testIsEmptyReturnsTrueIfStackIsEmpty(): void
55+
{
56+
$stack = new ArrayStack();
57+
$this->assertTrue($stack->isEmpty());
58+
$stack->push(1);
59+
$this->assertFalse($stack->isEmpty());
60+
}
61+
62+
// Test getting the size of the stack
63+
public function testSizeReturnsNumberOfElementsInStack(): void
64+
{
65+
$stack = new ArrayStack();
66+
$this->assertSame(0, $stack->size());
67+
$stack->push(1);
68+
$stack->push(2);
69+
$this->assertSame(2, $stack->size());
70+
}
71+
72+
// Test clearing the stack
73+
public function testClearRemovesAllElementsFromStack(): void
74+
{
75+
$stack = new ArrayStack();
76+
$stack->push(1);
77+
$stack->push(2);
78+
$stack->clear();
79+
$this->assertTrue($stack->isEmpty());
80+
}
81+
82+
// Test converting the stack to an array
83+
public function testGetItemsReturnsAllElementsInStack(): void
84+
{
85+
$stack = new ArrayStack();
86+
$stack->push(1);
87+
$stack->push(2);
88+
$this->assertSame([2, 1], $stack->getItems());
89+
}
90+
91+
// Test stack with various data types
92+
public function testStackWithVariousDataTypes(): void
93+
{
94+
$stack = new ArrayStack();
95+
$stack->push(123);
96+
$stack->push('string');
97+
$stack->push([1, 2, 3]);
98+
$stack->push(new \stdClass());
99+
100+
$this->assertInstanceOf(\stdClass::class, $stack->pop());
101+
$this->assertSame([1, 2, 3], $stack->pop());
102+
$this->assertSame('string', $stack->pop());
103+
$this->assertSame(123, $stack->pop());
104+
}
105+
106+
// Test stack behavior after mixed operations
107+
public function testStackBehaviorAfterMixedOperations(): void
108+
{
109+
$stack = new ArrayStack();
110+
$stack->push(1);
111+
$stack->push(2);
112+
$stack->pop();
113+
$stack->push(3);
114+
$stack->clear();
115+
$stack->push(4);
116+
$stack->push(5);
117+
118+
$this->assertSame(5, $stack->pop());
119+
$this->assertSame(4, $stack->peek());
120+
}
121+
122+
// Test LIFO behavior
123+
public function testStackFollowsLifoOrder(): void
124+
{
125+
$stack = new ArrayStack();
126+
$stack->push(1);
127+
$stack->push(2);
128+
$stack->push(3);
129+
130+
$this->assertSame(3, $stack->pop());
131+
$this->assertSame(2, $stack->pop());
132+
$this->assertSame(1, $stack->pop());
133+
}
134+
}

0 commit comments

Comments
 (0)