diff --git a/codes/php/chapter_stack_and_queue/array_deque.php b/codes/php/chapter_stack_and_queue/array_deque.php new file mode 100644 index 000000000..283a54a44 --- /dev/null +++ b/codes/php/chapter_stack_and_queue/array_deque.php @@ -0,0 +1,163 @@ +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; diff --git a/codes/php/chapter_stack_and_queue/array_queue.php b/codes/php/chapter_stack_and_queue/array_queue.php new file mode 100644 index 000000000..e6618401b --- /dev/null +++ b/codes/php/chapter_stack_and_queue/array_queue.php @@ -0,0 +1,123 @@ +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; +} diff --git a/codes/php/chapter_stack_and_queue/array_stack.php b/codes/php/chapter_stack_and_queue/array_stack.php new file mode 100644 index 000000000..8123df362 --- /dev/null +++ b/codes/php/chapter_stack_and_queue/array_stack.php @@ -0,0 +1,91 @@ +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; diff --git a/codes/php/chapter_stack_and_queue/deque.php b/codes/php/chapter_stack_and_queue/deque.php new file mode 100644 index 000000000..0f47292be --- /dev/null +++ b/codes/php/chapter_stack_and_queue/deque.php @@ -0,0 +1,43 @@ +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; diff --git a/codes/php/chapter_stack_and_queue/linkedlist_deque.php b/codes/php/chapter_stack_and_queue/linkedlist_deque.php new file mode 100644 index 000000000..7d44b9b2b --- /dev/null +++ b/codes/php/chapter_stack_and_queue/linkedlist_deque.php @@ -0,0 +1,199 @@ +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; diff --git a/codes/php/chapter_stack_and_queue/linkedlist_queue.php b/codes/php/chapter_stack_and_queue/linkedlist_queue.php new file mode 100644 index 000000000..fa56051cf --- /dev/null +++ b/codes/php/chapter_stack_and_queue/linkedlist_queue.php @@ -0,0 +1,115 @@ +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; diff --git a/codes/php/chapter_stack_and_queue/linkedlist_stack.php b/codes/php/chapter_stack_and_queue/linkedlist_stack.php new file mode 100644 index 000000000..6f94eb332 --- /dev/null +++ b/codes/php/chapter_stack_and_queue/linkedlist_stack.php @@ -0,0 +1,103 @@ +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; diff --git a/codes/php/chapter_stack_and_queue/queue.php b/codes/php/chapter_stack_and_queue/queue.php new file mode 100644 index 000000000..a9d40b68c --- /dev/null +++ b/codes/php/chapter_stack_and_queue/queue.php @@ -0,0 +1,36 @@ +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; diff --git a/codes/php/chapter_stack_and_queue/stack.php b/codes/php/chapter_stack_and_queue/stack.php new file mode 100644 index 000000000..1d41bf099 --- /dev/null +++ b/codes/php/chapter_stack_and_queue/stack.php @@ -0,0 +1,38 @@ +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;