feat: Add PHP Codes for chapter_stack_and_queue

This commit is contained in:
DoWake 2024-05-19 23:06:03 +08:00
parent 70df1515c1
commit 2f8572fd4f
9 changed files with 911 additions and 0 deletions

View File

@ -0,0 +1,163 @@
<?php
/**
* File: array_deque.php
* Created Time: 2024-05-19
* Author: DoWake (admin@mengxing.cc)
*/
/* 基于环形数组实现的双向队列 */
class ArrayDeque
{
private $nums; // 用于存储双向队列元素的数组
private $front; // 队首指针,指向队首元素
private $queSize; // 双向队列长度
/* 构造方法 */
public function __construct($capacity)
{
$this->nums = array_fill(0, $capacity, 0);
$this->front = 0;
$this->queSize = 0;
}
/* 获取双向队列的容量 */
public function capacity()
{
return count($this->nums);
}
/* 获取双向队列的长度 */
public function size()
{
return $this->queSize;
}
/* 判断双向队列是否为空 */
public function isEmpty()
{
return $this->queSize === 0;
}
/* 计算环形数组索引 */
private function index($i)
{
// 通过取余操作实现数组首尾相连
// 当 i 越过数组尾部后,回到头部
// 当 i 越过数组头部后,回到尾部
return ($i + $this->capacity()) % $this->capacity();
}
/* 队首入队 */
public function pushFirst($num)
{
if ($this->queSize === $this->capacity()) {
echo '双向队列已满' . PHP_EOL;
return;
}
// 队首指针向左移动一位
// 通过取余操作实现 front 越过数组头部后回到尾部
$this->front = $this->index($this->front - 1);
// 将 num 添加至队首
$this->nums[$this->front] = $num;
$this->queSize++;
}
/* 队尾入队 */
public function pushLast($num)
{
if ($this->queSize === $this->capacity()) {
echo '双向队列已满' . PHP_EOL;
return;
}
// 计算队尾指针,指向队尾索引 + 1
$rear = $this->index($this->front + $this->queSize);
// 将 num 添加至队尾
$this->nums[$rear] = $num;
$this->queSize++;
}
/* 队首出队 */
public function popFirst()
{
$num = $this->peekFirst();
// 队首指针向后移动一位
$this->front = $this->index($this->front + 1);
$this->queSize--;
return $num;
}
/* 队尾出队 */
public function popLast()
{
$num = $this->peekLast();
$this->queSize--;
return $num;
}
/* 访问队首元素 */
public function peekFirst()
{
if ($this->isEmpty()) {
throw new Error('The Deque Is Empty.');
}
return $this->nums[$this->front];
}
/* 访问队尾元素 */
public function peekLast()
{
if ($this->isEmpty()) {
throw new Error('The Deque Is Empty.');
}
// 计算尾元素索引
$last = $this->index($this->front + $this->queSize - 1);
return $this->nums[$last];
}
/* 返回数组用于打印 */
public function toArray()
{
// 仅转换有效长度范围内的列表元素
$res = [];
for ($i = 0, $j = $this->front; $i < $this->queSize; $i++, $j++) {
$res[$i] = $this->nums[$this->index($j)];
}
return $res;
}
}
/* Driver Code */
/* 初始化双向队列 */
$deque = new ArrayDeque(10);
$deque->pushLast(3);
$deque->pushLast(2);
$deque->pushLast(5);
echo '双向队列 deque = [' . join(', ', $deque->toArray()) . ']' . PHP_EOL;
/* 访问元素 */
$peekFirst = $deque->peekFirst();
echo "队首元素 peekFirst = {$peekFirst}" . PHP_EOL;
$peekLast = $deque->peekLast();
echo "队尾元素 peekLast = {$peekLast}" . PHP_EOL;
/* 元素入队 */
$deque->pushLast(4);
echo '元素 4 队尾入队后 deque = [' . join(', ', $deque->toArray()) . ']' . PHP_EOL;
$deque->pushFirst(1);
echo '元素 1 队首入队后 deque = [' . join(', ', $deque->toArray()) . ']' . PHP_EOL;
/* 元素出队 */
$popLast = $deque->popLast();
echo "队尾出队元素 = {$popLast},队尾出队后 deque = [" . join(', ', $deque->toArray()) . "]" . PHP_EOL;
$popFirst = $deque->popFirst();
echo "队首出队元素 = {$popFirst},队首出队后 deque = [" . join(', ', $deque->toArray()) . "]" . PHP_EOL;
/* 获取双向队列的长度 */
$size = $deque->size();
echo "双向队列长度 size = {$size}" . PHP_EOL;
/* 判断双向队列是否为空 */
$isEmpty = $deque->isEmpty();
$isEmptyStr = $isEmpty ? 'true' : 'false';
echo "双向队列是否为空 = {$isEmptyStr}" . PHP_EOL;

View File

@ -0,0 +1,123 @@
<?php
/**
* File: array_queue.php
* Created Time: 2024-05-19
* Author: DoWake (admin@mengxing.cc)
*/
/* 基于环形数组实现的队列 */
class ArrayQueue
{
private $nums; // 用于存储队列元素的数组
private $front; // 队首指针,指向队首元素
private $queSize; // 队列长度
/* 构造方法 */
public function __construct($capacity)
{
$this->nums = array_fill(0, $capacity, 0);
$this->front = 0;
$this->queSize = 0;
}
/* 获取队列的容量 */
public function capacity()
{
return count($this->nums);
}
/* 获取队列的长度 */
public function size()
{
return $this->queSize;
}
/* 判断队列是否为空 */
public function isEmpty()
{
return $this->queSize === 0;
}
/* 入队 */
public function push($num)
{
if ($this->queSize === $this->capacity()) {
echo '队列已满' . PHP_EOL;
return;
}
// 计算队尾指针,指向队尾索引 + 1
// 通过取余操作实现 rear 越过数组尾部后回到头部
$rear = ($this->front + $this->queSize) % $this->capacity();
// 将 num 添加至队尾
$this->nums[$rear] = $num;
$this->queSize++;
}
/* 出队 */
public function pop()
{
$num = $this->peek();
// 队首指针向后移动一位,若越过尾部,则返回到数组头部
$this->front = ($this->front + 1) % $this->capacity();
$this->queSize--;
return $num;
}
/* 访问队首元素 */
public function peek()
{
if ($this->isEmpty()) {
throw new Exception('The Quque Is Empty.');
}
return $this->nums[$this->front];
}
/* 返回数组 */
public function toArray()
{
// 仅转换有效长度范围内的列表元素
$res = [];
for ($i = 0, $j = $this->front; $i < $this->queSize; $i++, $j++) {
$res[$i] = $this->nums[$j % $this->capacity()];
}
return $res;
}
}
/* Driver Code */
/* 初始化队列 */
$capacity = 10;
$queue = new ArrayQueue($capacity);
/* 元素入队 */
$queue->push(1);
$queue->push(3);
$queue->push(2);
$queue->push(5);
$queue->push(4);
echo '队列 queue = [' . join(', ', $queue->toArray()) . ']' . PHP_EOL;
/* 访问队首元素 */
$peek = $queue->peek();
echo "队首元素 peek = {$peek}" . PHP_EOL;
/* 元素出队 */
$pop = $queue->pop();
echo "出队元素 pop = {$pop},出队后 queue = [" . join(', ', $queue->toArray()) . "]" . PHP_EOL;
/* 获取队列的长度 */
$size = $queue->size();
echo "队列长度 size = {$size}" . PHP_EOL;
/* 判断队列是否为空 */
$isEmpty = $queue->isEmpty();
$isEmptyStr = $isEmpty ? 'true' : 'false';
echo "队列是否为空 = {$isEmptyStr}" . PHP_EOL;
/* 测试环形数组 */
for ($i = 0; $i < 10; $i++) {
$queue->push($i);
$queue->pop();
echo "{$i} 轮入队 + 出队后 queue = [" . join(', ', $queue->toArray()) . "]" . PHP_EOL;
}

View File

@ -0,0 +1,91 @@
<?php
/**
* File: array_stack.php
* Created Time: 2024-05-19
* Author: DoWake (admin@mengxing.cc)
*/
/* 基于数组实现的栈 */
class ArrayStack
{
private $stack;
/* 构造方法 */
public function __construct()
{
// 初始化列表(动态数组)
$this->stack = [];
}
/* 获取栈的长度 */
public function size()
{
return count($this->stack);
}
/* 判断栈是否为空 */
public function isEmpty()
{
return $this->size() === 0;
}
/* 入栈 */
public function push($num)
{
array_push($this->stack, $num);
}
/* 出栈 */
public function pop()
{
if ($this->isEmpty()) {
throw new Exception('The Stack Is Empty.');
}
return array_pop($this->stack);
}
/* 访问栈顶元素 */
public function peek()
{
if ($this->isEmpty()) {
throw new Exception('The Stack Is Empty.');
}
return end($this->stack);
}
/* 将 List 转化为 Array 并返回 */
public function toArray()
{
return $this->stack;
}
}
/* Driver Code */
/* 初始化栈 */
$stack = new ArrayStack();
/* 元素入栈 */
$stack->push(1);
$stack->push(3);
$stack->push(2);
$stack->push(5);
$stack->push(4);
echo '栈 stack = [' . join(', ', $stack->toArray()) . ']' . PHP_EOL;
/* 访问栈顶元素 */
$peek = $stack->peek();
echo "栈顶元素 peek = {$peek}" . PHP_EOL;
/* 元素出栈 */
$pop = $stack->pop();
echo "出栈元素 pop = {$pop},出栈后 stack = [" . join(', ', $stack->toArray()) . ']' . PHP_EOL;
/* 获取栈的长度 */
$size = $stack->size();
echo "栈的长度 size = {$size}" . PHP_EOL;
/* 判断是否为空 */
$isEmpty = $stack->isEmpty();
$isEmptyStr = $isEmpty ? 'true' : 'false';
echo "栈是否为空 = {$isEmptyStr}" . PHP_EOL;

View File

@ -0,0 +1,43 @@
<?php
/**
* File: deque.php
* Created Time: 2024-05-19
* Author: DoWake (admin@mengxing.cc)
*/
/* Driver Code */
/* 初始化双向队列 */
// 使用SplDoublyLinkedList类实现双向队列
$deque = new SplDoublyLinkedList();
$deque->push(3);
$deque->push(2);
$deque->push(5);
echo '双向队列 deque = [' . join(', ', iterator_to_array($deque)) . ']' . PHP_EOL;
/* 访问元素 */
$peekFirst = $deque->bottom();
echo "队首元素 peekFirst = {$peekFirst}" . PHP_EOL;
$peekLast = $deque->top();
echo "队尾元素 peekLast = {$peekLast}" . PHP_EOL;
/* 元素入队 */
$deque->push(4);
echo '元素 4 队尾入队后 deque = [' . join(', ', iterator_to_array($deque)) . ']' . PHP_EOL;
$deque->unshift(1);
echo '元素 1 队首入队后 deque = [' . join(', ', iterator_to_array($deque)) . ']' . PHP_EOL;
/* 元素出队 */
$popLast = $deque->pop();
echo "队尾出队元素 = {$popLast},队尾出队后 deque = [" . join(', ', iterator_to_array($deque)) . ']' . PHP_EOL;
$popFirst = $deque->shift();
echo "队首出队元素 = {$popFirst},队首出队后 deque = [" . join(', ', iterator_to_array($deque)) . ']' . PHP_EOL;
/* 获取双向队列的长度 */
$size = $deque->count();
echo "双向队列长度 size = {$size}" . PHP_EOL;
/* 判断双向队列是否为空 */
$isEmpty = $deque->isEmpty();
$isEmptyStr = $isEmpty ? 'true' : 'false';
echo "双向队列是否为空 = {$isEmptyStr}" . PHP_EOL;

View File

@ -0,0 +1,199 @@
<?php
/**
* File: linkedlist_deque.php
* Created Time: 2024-05-19
* Author: DoWake (admin@mengxing.cc)
*/
/* 双向链表节点 */
class ListNode
{
public $val; // 节点值
public $next; // 后继节点引用
public $prev; // 前驱节点引用
/* 构造方法 */
public function __construct($val)
{
$this->val = $val;
$this->prev = null;
$this->next = null;
}
}
/* 基于双向链表实现的双向队列 */
class LinkedListDeque
{
private $front; // 头节点 front
private $rear; // 尾节点 rear
private $queSize = 0; // 双向队列的长度
/* 构造方法 */
public function __construct()
{
$this->front = null;
$this->rear = null;
}
/* 获取双向队列的长度 */
public function size()
{
return $this->queSize;
}
/* 判断双向队列是否为空 */
public function isEmpty()
{
return $this->size() === 0;
}
/* 入队操作 */
private function push($num, $isFront)
{
$node = new ListNode($num);
// 若链表为空,则令 front 和 rear 都指向 node
if ($this->isEmpty()) {
$this->front = $node;
$this->rear = $node;
}
// 队首入队操作
else if ($isFront) {
// 将 node 添加至链表头部
$this->front->prev = $node;
$node->next = $this->front;
$this->front = $node; // 更新头节点
}
// 队尾入队操作
else {
// 将 node 添加至链表尾部
$this->rear->next = $node;
$node->prev = $this->rear;
$this->rear = $node; // 更新尾节点
}
$this->queSize++; // 更新队列长度
}
/* 队首入队 */
public function pushFirst($num)
{
$this->push($num, true);
}
/* 队尾入队 */
public function pushLast($num)
{
$this->push($num, false);
}
/* 出队操作 */
private function pop($isFront)
{
if ($this->isEmpty()) {
throw new Exception('The Deque Is Empty.');
}
$val = 0;
// 队首出队操作
if ($isFront) {
$val = $this->front->val; // 暂存头节点值
// 删除头节点
$fNext = $this->front->next;
if ($fNext !== null) {
$fNext->prev = null;
$this->front->next = null;
}
$this->front = $fNext; // 更新头节点
}
// 队尾出队操作
else {
$val = $this->rear->val; // 暂存尾节点值
// 删除尾节点
$rPrev = $this->rear->prev;
if ($rPrev !== null) {
$rPrev->next = null;
$this->rear->prev = null;
}
$this->rear = $rPrev; // 更新尾节点
}
$this->queSize--; // 更新队列长度
return $val;
}
/* 队首出队 */
public function popFirst()
{
return $this->pop(true);
}
/* 队尾出队 */
public function popLast()
{
return $this->pop(false);
}
/* 访问队首元素 */
public function peekFirst()
{
if ($this->isEmpty()) {
throw new Exception('The Deque Is Empty.');
}
return $this->front->val;
}
/* 访问队尾元素 */
public function peekLast()
{
if ($this->isEmpty()) {
throw new Exception('The Deque Is Empty.');
}
return $this->rear->val;
}
/* 返回数组用于打印 */
public function toArray()
{
$node = $this->front;
$res = [];
$length = $this->size();
for ($i = 0; $i < $length; $i++) {
$res[$i] = $node->val;
$node = $node->next;
}
return $res;
}
}
/* Driver Code */
/* 初始化双向队列 */
$deque = new LinkedListDeque();
$deque->pushLast(3);
$deque->pushLast(2);
$deque->pushLast(5);
echo '双向队列 deque = [' . join(', ', $deque->toArray()) . ']' . PHP_EOL;
/* 访问元素 */
$peekFirst = $deque->peekFirst();
echo "队首元素 peekFirst = {$peekFirst}" . PHP_EOL;
$peekLast = $deque->peekLast();
echo "队尾元素 peekLast = {$peekLast}" . PHP_EOL;
/* 元素入队 */
$deque->pushLast(4);
echo '元素 4 队尾入队后 deque = [' . join(', ', $deque->toArray()) . ']' . PHP_EOL;
$deque->pushFirst(1);
echo '元素 1 队首入队后 deque = [' . join(', ', $deque->toArray()) . ']' . PHP_EOL;
/* 元素出队 */
$popLast = $deque->popLast();
echo "队尾出队元素 = {$popLast},队尾出队后 deque = [" . join(', ', $deque->toArray()) . ']' . PHP_EOL;
$popFirst = $deque->popFirst();
echo "队首出队元素 = {$popFirst},队首出队后 deque = [" . join(', ', $deque->toArray()) . ']' . PHP_EOL;
/* 获取双向队列的长度 */
$size = $deque->size();
echo "双向队列长度 size = {$size}" . PHP_EOL;
/* 判断双向队列是否为空 */
$isEmpty = $deque->isEmpty();
$isEmptyStr = $isEmpty ? 'true' : 'false';
echo "双向队列是否为空 = {$isEmptyStr}" . PHP_EOL;

View File

@ -0,0 +1,115 @@
<?php
/**
* File: linkedlist_queue.php
* Created Time: 2024-05-19
* Author: DoWake (admin@mengxing.cc)
*/
require_once '../utils/ListNode.php';
/* 基于链表实现的队列 */
class LinkedListQueue
{
private $front; // 头节点 front
private $rear; // 尾节点 rear
private $queSize = 0;
/* 构造方法 */
public function __construct()
{
$this->front = null;
$this->rear = null;
}
/* 获取队列的长度 */
public function size()
{
return $this->queSize;
}
/* 判断队列是否为空 */
public function isEmpty()
{
return $this->size() === 0;
}
/* 入队 */
public function push($num)
{
// 在尾节点后添加 num
$node = new ListNode($num);
// 如果队列为空,则令头、尾节点都指向该节点
if ($this->front === null) {
$this->front = $node;
$this->rear = $node;
}
// 如果队列不为空,则将该节点添加到尾节点后
else {
$this->rear->next = $node;
$this->rear = $node;
}
$this->queSize++;
}
/* 出队 */
public function pop()
{
$num = $this->peek();
// 删除头节点
$this->front = $this->front->next;
$this->queSize--;
return $num;
}
/* 访问队首元素 */
public function peek()
{
if ($this->isEmpty()) {
throw new Exception('The Queue Is Empty.');
}
return $this->front->val;
}
/* 将链表转化为 Array 并返回 */
public function toArray()
{
$node = $this->front;
$res = [];
$length = $this->size();
for ($i = 0; $i < $length; $i++) {
$res[$i] = $node->val;
$node = $node->next;
}
return $res;
}
}
/* Driver Code */
/* 初始化队列 */
$queue = new LinkedListQueue();
/* 元素入队 */
$queue->push(1);
$queue->push(3);
$queue->push(2);
$queue->push(5);
$queue->push(4);
echo '队列 queue = [' . join(', ', $queue->toArray()) . ']' . PHP_EOL;
/* 访问队首元素 */
$peek = $queue->peek();
echo "队首元素 peek = {$peek}" . PHP_EOL;
/* 元素出队 */
$pop = $queue->pop();
echo "出队元素 pop = {$pop},出队后 queue = [" . join(', ', $queue->toArray()) . ']' . PHP_EOL;
/* 获取队列的长度 */
$size = $queue->size();
echo "队列长度 size = {$size}" . PHP_EOL;
/* 判断队列是否为空 */
$isEmpty = $queue->isEmpty();
$isEmptyStr = $isEmpty ? 'true' : 'false';
echo "队列是否为空 = {$isEmptyStr}" . PHP_EOL;

View File

@ -0,0 +1,103 @@
<?php
/**
* File: linkedlist_stack.php
* Created Time: 2024-05-19
* Author: DoWake (admin@mengxing.cc)
*/
require_once '../utils/ListNode.php';
/* 基于链表实现的栈 */
class LinkedListStack
{
private $stackPeek; // 将头节点作为栈顶
private $stkSize = 0; // 栈的长度
/* 构造方法 */
public function __construct()
{
$this->stackPeek = null;
}
/* 获取栈的长度 */
public function size()
{
return $this->stkSize;
}
/* 判断栈是否为空 */
public function isEmpty()
{
return $this->size() === 0;
}
/* 入栈 */
public function push($num)
{
$node = new ListNode($num);
$node->next = $this->stackPeek;
$this->stackPeek = $node;
$this->stkSize++;
}
/* 出栈 */
public function pop()
{
$num = $this->peek();
$this->stackPeek = $this->stackPeek->next;
$this->stkSize--;
return $num;
}
/* 访问栈顶元素 */
public function peek()
{
if ($this->isEmpty()) {
throw new Exception('The Stack Is Empty.');
}
return $this->stackPeek->val;
}
/* 将 List 转化为 Array 并返回 */
public function toArray()
{
$node = $this->stackPeek;
$length = $this->size();
$res = array_fill(0, $length, 0);
for ($i = $length - 1; $i >= 0; $i--) {
$res[$i] = $node->val;
$node = $node->next;
}
return $res;
}
}
/* Driver Code */
/* 初始化栈 */
$stack = new LinkedListStack();
/* 元素入栈 */
$stack->push(1);
$stack->push(3);
$stack->push(2);
$stack->push(5);
$stack->push(4);
echo '栈 stack = [' . join(', ', $stack->toArray()) . ']' . PHP_EOL;
/* 访问栈顶元素 */
$peek = $stack->peek();
echo "栈顶元素 peek = {$peek}" . PHP_EOL;
/* 元素出栈 */
$pop = $stack->pop();
echo "出栈元素 pop = {$pop},出栈后 stack = [" . join(', ', $stack->toArray()) . ']' . PHP_EOL;
/* 获取栈的长度 */
$size = $stack->size();
echo "栈的长度 size = {$size}" . PHP_EOL;
/* 判断是否为空 */
$isEmpty = $stack->isEmpty();
$isEmptyStr = $isEmpty ? 'true' : 'false';
echo "栈是否为空 = {$isEmptyStr}" . PHP_EOL;

View File

@ -0,0 +1,36 @@
<?php
/**
* File: queue.php
* Created Time: 2024-05-19
* Author: DoWake (admin@mengxing.cc)
*/
/* Driver Code */
/* 初始化队列 */
$queue = new SplQueue();
/* 元素入队 */
$queue->enqueue(1);
$queue->enqueue(3);
$queue->enqueue(2);
$queue->enqueue(5);
$queue->enqueue(4);
echo '队列 queue = [' . join(', ', iterator_to_array($queue)) . ']' . PHP_EOL;
/* 访问队首元素 */
$peek = $queue->bottom();
echo "队首元素 peek = {$peek}" . PHP_EOL;
/* 元素出队 */
$pop = $queue->dequeue();
echo "出队元素 pop = {$pop},出队后 queue = [" . join(', ', iterator_to_array($queue)) . ']' . PHP_EOL;
/* 获取队列的长度 */
$size = $queue->count();
echo "队列长度 size = {$size}" . PHP_EOL;
/* 判断队列是否为空 */
$isEmpty = $queue->isEmpty();
$isEmptyStr = $isEmpty ? 'true' : 'false';
echo "队列是否为空 = {$isEmptyStr}" . PHP_EOL;

View File

@ -0,0 +1,38 @@
<?php
/**
* File: stack.php
* Created Time: 2024-05-19
* Author: DoWake (admin@mengxing.cc)
*/
/* Driver Code */
/* 初始化栈 */
$stack = new SplStack();
/* 元素入栈 */
$stack->push(1);
$stack->push(3);
$stack->push(2);
$stack->push(5);
$stack->push(4);
$stackStr = '[' . join(', ', array_reverse(iterator_to_array($stack))) . ']';
echo "栈 stack = {$stackStr}" . PHP_EOL;
/* 访问栈顶元素 */
$peek = $stack->top();
echo "栈顶元素 peek = {$peek}" . PHP_EOL;
/* 元素出栈 */
$pop = $stack->pop();
$stackStr = '[' . join(', ', array_reverse(iterator_to_array($stack))) . ']';
echo "出栈元素 pop = {$pop},出栈后 stack = {$stackStr}" . PHP_EOL;
/* 获取栈的长度 */
$size = $stack->count();
echo "栈的长度 size = {$size}" . PHP_EOL;
/* 判断是否为空 */
$isEmpty = $stack->isEmpty();
$isEmptyStr = $isEmpty ? 'true' : 'false';
echo "栈是否为空 = {$isEmptyStr}" . PHP_EOL;