实战 PHP 数据结构基础之栈

栈和队列

栈和队列和之前讲到的实战PHP数据结构基础之双链表
一样都是线性结构。

栈有什么特点

栈遵循后进先出的原则(LIFO)。这意味着栈只有一个出口用来压入元素和弹出元素,当我们执行压入或者弹出操作的时候要注意栈是否已满或者栈是否是空的。

常见操作

还是废话不多说,直接来看我们对栈执行的常用操作。

  • push
  • pop
  • top
  • isEmpty
  • ...

PHP实现

首先我们定义一个StackInterface。

interface StackInterface
{
    public function push(string $item);
    public function pop();
    public function top();
    public function isEmpty();
}

来看基于数组的栈实现

class ArrStack implements StackInterface
{
    private $stack;
    private $limit;

    public function __construct(int $limit = 20)
    {
        $this->limit = $limit;
        $this->stack = [];
    }

    public function __get($val)
    {
        return $this->$val;
    }

    public function push(string $data = null)
    {
        if (count($this->stack) < $this->limit) {
            array_push($this->stack, $data);
        } else {
            throw new \OverflowException('stack is overflow');
        }
    }

    public function pop()
    {
        if ($this->isEmpty()) {
            throw new \UnderflowException('stack is empty');
        } else {
            return array_pop($this->stack);
        }
    }

    public function isEmpty()
    {
        return empty($this->stack);
    }

    public function top()
    {
        return end($this->stack);
    }

得益于PHP强大的array结构,我们轻而易举的写出来了栈的基本操作方法。果然世界上最好的语言名不虚传。

那有同学说了,你说栈和之前的链表都是线性结构,那可不可以直接使用链表实现栈呢?这个问题非常犀利啊,答案是可以的。

可能机智的同学已经猜到了,我之前已经定义了一个栈接口,那栈的实现肯定不止只有上面一种哈。来看基于链表的实现。

class LinkedListStack implements StackInterface
{
    private $stack;
    private $limit;

    public function __construct(int $limit)
    {
        $this->limit = $limit;
        $this->stack = new LinkedList();
    }

    public function top()
    {
        return $this->stack->getNthNode($this->stack->getSize() - 1)->data;
    }

    public function isEmpty()
    {
        return $this->stack->getSize() === 0;
    }

    public function pop()
    {
        if ($this->isEmpty()) {
            throw new \UnderflowException('stack is empty');
        } else {
            $lastItem = $this->top();
            $this->stack->deleteLast();

            return $lastItem;
        }
    }

    public function push(string $item)
    {
        if ($this->stack->getSize() < $this->limit) {
            $this->stack->insert($item);
        } else {
            throw new \OverflowException('stack is overflow');
        }
    }

里面涉及到了之前的链表实现,不了解细节的同学可以去这里看看。有同学又问,那栈到底有什么用处?这个问题非常好,来看一个需求。

请实现一个数学表达式检查类,输入一个下面表达式,预期结果为true。

"8 * (9 -2) + { (4 * 5) / ( 2 * 2) }

下面的为false。

"5 * 8 * 9 / ( 3 * 2 ) )"

下面的也为false。

"[{ (2 * 7) + ( 15 - 3) ]"

自己想一下,再往下看实现。

class ExpressionChecker
{
    //$expressions[] = "8 * (9 -2) + { (4 * 5) / ( 2 * 2) }";
    //$expressions[] = "5 * 8 * 9 / ( 3 * 2 ) )";
    //$expressions[] = "[{ (2 * 7) + ( 15 - 3) ]";

    public function check(string $expression): bool
    {
        $stack = new \SplStack();

        foreach (str_split($expression) as $item) {
            switch ($item) {
                case '{':
                case '[':
                case '(':
                    $stack->push($item);
                    break;

                case '}':
                case ']':
                case ')':
                    if ($stack->isEmpty()) return false;

                    $last = $stack->pop();

                    if (
                        $item == '{' && $last != '}' ||
                        $item == '(' && $last != ')' ||
                        $item == '[' && $last != ']'
                    )
                        return false;

                    break;
            }
        }

        if ($stack->isEmpty()) {
            return true;
        }

        return false;
    }
}

专题系列

PHP基础数据结构专题系列目录地址:地址 主要使用PHP语法总结基础的数据结构和算法。还有我们日常PHP开发中容易忽略的基础知识和现代PHP开发中关于规范、部署、优化的一些实战性建议,同时还有对Javascript语言特点的深入研究。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 5

我一位你会讲 php 自带的 栈 的实现原理

5年前 评论

public function check(string $expression): bool
这个bool 是什么声明语法没见过呀。

5年前 评论

@sanmu_sir 返回值类型声明

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!