Skip to content

Commit 03b5f05

Browse files
authored
Merge pull request #8 from CrimsonNynja/Binary-Heap
Binary heap
2 parents c827b21 + 0f6a7f6 commit 03b5f05

File tree

5 files changed

+358
-35
lines changed

5 files changed

+358
-35
lines changed

README.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
This repo is designed to have all common trees used in an easy to use php way
66

7-
Current included are implementations of a Binary Search Tree, Rope and a Generic Tree, with more to come!
7+
Current included are implementations of a Binary Search Tree, Rope, Binary Heap, and a Generic Tree, with more to come!
88

9-
All tests are written in PHP Unit, and all code is written in the PSR-4 standards. Php Trees also requires PHP 7.2 or above
9+
All tests are written in PHP Unit, and all code is written in the PSR-4 standards. Php Trees also requires PHP 7.4 or above
1010

1111
PHP Trees can be installed through composer with
1212

@@ -23,23 +23,31 @@ To use the binary search tree, include the correct file and create it as such
2323
```php
2424
use PhpTrees\BinarySearchTree;
2525

26-
$b = new PhpTrees\BinarySearchTree(5);
26+
$b = new BinarySearchTree(5);
2727
```
2828

2929
To use the Rope
3030

3131
```php
3232
use PhpTrees\Rope;
3333

34-
$r = new PhpTrees\Rope("This is a Rope!");
34+
$r = new Rope("This is a Rope!");
35+
```
36+
37+
To use the Binary Heap
38+
39+
```php
40+
use PhpTrees\BinaryHeap;
41+
42+
$h = new BinaryHeap();
3543
```
3644

3745
To use the Generic Tree
3846

3947
```php
4048
use PhpTrees\GenericTree;
4149

42-
$g = new PhpTrees\GenericTree(4.1);
50+
$g = new GenericTree(4.1);
4351
```
4452

4553
This will create a binary search tree with a root of the value 5\
@@ -50,6 +58,5 @@ For a more detailed description of the features of PHP Trees, check out the wiki
5058

5159
tree balancing options\
5260
2-3 tree\
53-
Heep\
5461
B-Tree\
5562
search/traversal types (depth first search breadth first search, etc)

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "crimson-nynja/php-trees",
33
"description": "PHP implementation of various Trees",
44
"license": "GPL-3.0-or-later",
5-
"keywords": ["PHP", "Trees", "Tree", "Binary Search Tree", "BST", "Rope"],
5+
"keywords": ["PHP", "Trees", "Tree", "Binary Search Tree", "BST", "Rope", "Binary Heap", "Heap", "Generic Tree"],
66
"authors": [
77
{
88
"name": "Hudson Cassidy",

composer.lock

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

src/PhpTrees/BinaryHeap.php

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
<?php
2+
3+
namespace PhpTrees;
4+
5+
/**
6+
* implementation of a binary heap (currently just a Min Heap)
7+
* this is an array implementation, and as such stores everything in an array internally
8+
*/
9+
class BinaryHeap
10+
{
11+
/* internal array to store the heap in */
12+
private array $heap = [];
13+
14+
/**
15+
* constructs the heap with the initial root, if given
16+
* as this is a heap the root value may not remain consistent
17+
*
18+
* @param mixed|null $root the initial root of the heap
19+
*/
20+
public function __construct($root = null)
21+
{
22+
if ($root !== null) {
23+
$this->insert($root);
24+
}
25+
}
26+
27+
/**
28+
* constructs a heap from an array
29+
* this function will be much faster then inserting each element from that array individually
30+
* Note that if any values in the heap already exists, they will be replaced here
31+
*
32+
* @param array<mixed> $values the array to build the heap on
33+
*/
34+
public function constructFromArray(array $values) : void
35+
{
36+
$this->heap = $values;
37+
$this->heapify();
38+
}
39+
40+
/**
41+
* inserts a value into the heap
42+
*
43+
* @param mixed $value the value to add
44+
*/
45+
public function insert($value) : void
46+
{
47+
$this->heap[] = $value;
48+
$this->bubbleUp(sizeof($this->heap) - 1);
49+
}
50+
51+
/**
52+
* inserts multiple values into the heap
53+
*
54+
* @param mixed ...$values the variatic values to add, can be of differing types
55+
*/
56+
public function insertMultiple(...$values) : void
57+
{
58+
foreach($values as $value) {
59+
$this->insert($value);
60+
}
61+
}
62+
63+
/**
64+
* deletes the minimum value from the heap
65+
*
66+
* @return mixed returns teh element removed
67+
*/
68+
public function deleteMin()
69+
{
70+
if ($this->heap !== []) {
71+
$ret = $this->heap[0];
72+
$this->heap[0] = array_pop($this->heap);
73+
$this->bubbleDown(0);
74+
return $ret;
75+
}
76+
}
77+
78+
/**
79+
* gets the smallest value in the heap, if it exists
80+
*
81+
* @return mixed|null the smallest value in the heap
82+
*/
83+
public function getMinValue()
84+
{
85+
if ($this->heap !== []) {
86+
return $this->heap[0];
87+
}
88+
return null;
89+
}
90+
91+
/**
92+
* gets the max element in the heap, if it exists
93+
*
94+
* @return mixed|null the maximum element in the heap
95+
*/
96+
public function getMaxValue()
97+
{
98+
if ($this->heap !== []) {
99+
$max = $this->heap[(int)sizeof($this->heap) / 2];
100+
for ($i = 1 + (sizeof($this->heap) / 2); $i < sizeof($this->heap); ++$i) {
101+
$max = max($max, $this->heap[$i]);
102+
}
103+
return $max;
104+
}
105+
return null;
106+
}
107+
108+
/**
109+
* gets the internal representation of the heap
110+
*
111+
* @return array the heap representation in the array
112+
*/
113+
public function getInternalArray() : array
114+
{
115+
return $this->heap;
116+
}
117+
118+
/**
119+
* gets the amount of elements in the heap
120+
*
121+
* @return int the size of the heap
122+
*/
123+
public function getSize() : int
124+
{
125+
return sizeof($this->heap);
126+
}
127+
128+
/**
129+
* rebuilds the heap. This is useful if you want a heap from an array
130+
*/
131+
private function heapify() : void
132+
{
133+
for ($i = sizeof($this->heap) - 1; $i >= 0; --$i) {
134+
$this->bubbleDown($i);
135+
}
136+
}
137+
138+
/**
139+
* bubbles up the value in the heap, if it needs to
140+
*
141+
* @param int $index the index to start bubbling up from
142+
*/
143+
private function bubbleUp(int $index) : void
144+
{
145+
if ($index === 0) {
146+
return;
147+
}
148+
149+
$parentIndex = (int)($index - 1) / 2;
150+
151+
if ($this->heap[$parentIndex] > $this->heap[$index]) {
152+
$dummy = $this->heap[$parentIndex];
153+
$this->heap[$parentIndex] = $this->heap[$index];
154+
$this->heap[$index] = $dummy;
155+
$this->bubbleUp($parentIndex);
156+
}
157+
}
158+
159+
/**
160+
* turns an array into a heap
161+
* more efficient then inserting each element individually if an array is already created
162+
*
163+
* @param int $index the index to bubble down on
164+
*/
165+
private function bubbleDown(int $index) : void
166+
{
167+
$length = sizeof($this->heap);
168+
$leftIndex = (2 * $index) + 1;
169+
$rightIndex = (2 * $index) + 2;
170+
171+
if ($leftIndex >= $length) {
172+
return;
173+
}
174+
175+
$minIndex = $index;
176+
177+
if ($this->heap[$index] > $this->heap[$leftIndex]) {
178+
$minIndex = $leftIndex;
179+
}
180+
181+
if (($rightIndex < $length) && ($this->heap[$minIndex] > $this->heap[$rightIndex])) {
182+
$minIndex = $rightIndex;
183+
}
184+
185+
if ($minIndex !== $index) {
186+
$dummy = $this->heap[$index];
187+
$this->heap[$index] = $this->heap[$minIndex];
188+
$this->heap[$minIndex] = $dummy;
189+
$this->bubbleDown($minIndex);
190+
}
191+
}
192+
}

0 commit comments

Comments
 (0)