PHP 中缀表达式转后缀表达式

<?php

namespace app\controller;

use app\BaseController;

class Anti extends BaseController
{

    private $operatorAdd = '+';

    private $operatorReduce = '-';

    private $operatorRide = '*';

    private $operatorExcept = '/';

    private $left = '(';

    private $right = ')';

    /**
     * 存放数字
     * @var string
     */
    private $bucket = array();

    /**
     * 存放表达式
     */
    private $operatorBucket = array();


     
    public function execute()
    {


        // 转换工具 http://tools.jb51.net/jisuanqi/exp_jisuanqi

        try{
            $operator = [
                // '9', '+', '(', '3', '-', '1', ')', '*', '3', '+', '10', '/', '2'
                // '9', '+', '(', '5', '-', '3', ')', '*', '2', '+', '9', '/', '3',
                '9', '+', '(', '20','-','(', '5', '-', '3', ')', '*', '3',')', '*', '2', '+', '9', '/', '32', '+', '2', '/', '2'
                // '1', '+', '2', '-', '8'
            ];
            // 9+(5-3)*2+9/3
            // 9+(20-(5-3)*3)*2+9/32+2/2
    
            // 将运算符转化为 后缀表达式
            var_dump($this->toAntiPoland($operator));
      
            // // 运算
            // $result = 0;
            // for ($i=0; $i < count($this->bucket); $i++) { 
                
          
            //     if(in_array($this->bucket[$i], [
            //         $this->operatorAdd, 
            //         $this->operatorReduce, 
            //         $this->operatorRide, 
            //         $this->operatorExcept, 
            //         $this->left, $this->right])
            //     ) {
            //         $l = $this->bucket[$i-2];
            //         $r = $this->bucket[$i-1];
    
            //         switch ($this->bucket[$i]) {
            //             case '+':
            //                 $num = $l+$r;
            //                 break;
            //             case '-':
            //                 $num = $l-$r;
            //                 break;
            //             case '*':
            //                 $num = $l*$r;
            //                 break;
            //             case '/':
            //                 if($r <= 0) {
            //                     throw new \Exception("表达式错误!除数不能为0", 1);
            //                 }
            //                 $num = $l/$r;
            //                 break;
            //         }
            //         unset($this->bucket[$i-2]);
            //         unset($this->bucket[$i-1]);
            //         $this->bucket[$i] = $num;
            //         $this->bucket = array_values($this->bucket);
            //         $i=0;
            //         if(count($this->bucket) <= 1) {
            //             $result = array_pop($this->bucket);
            //             break;
            //         }
            //     }
            // }
            // var_dump($result);die;
        } catch(\Exception $e) {
            exit($e->getMessage());
        }
        

    }

    /**
     * 中缀表达式 转 后缀表达式
     */
    public function toAntiPoland($operator)
    {
        foreach ($operator as $key => $value) {

            // 判断是否运算符
            if(in_array($value, [$this->operatorAdd, $this->operatorReduce, $this->operatorRide, $this->operatorExcept, $this->left, $this->right])) {
              
                if($value === $this->right) {
                    // 查找第一个( 出现的位置
                    $leftFirstKey = $this->strLastKey($this->left);
                    for ($i=count($this->operatorBucket)-1; $i >= $leftFirstKey ; $i--) { 
                      
                        if(!in_array( $this->operatorBucket[$i], [$this->left, $this->right])) {
                            if($this->operatorBucket[$i] == $this->left) {
                                break;
                            }
                            $this->bucket[] = $this->operatorBucket[$i];
                        }
                        unset($this->operatorBucket[$i]);
                    }
                }else{
             
                    // 运算符比较
                    if(!empty($this->searchLastOper()) && !in_array($value, [$this->left, $this->right]) && $this->priority($this->searchLastOper()) > $this->priority($value) ) {
                        while (!empty($this->operatorBucket)) {
                            $e = array_pop($this->operatorBucket);
                            if($e == $this->left) {
                                break;
                            }
                            $this->bucket[] = $e;
                        }
                    }
                    $this->operatorBucket[] = $value;
                }
            }else{
                $this->bucket[] = $value;
            }
            $this->operatorBucket = array_values($this->operatorBucket);
         
        }

        // 取出全部运算符
        while (!empty($this->operatorBucket)) {
            $this->bucket[] =  array_pop($this->operatorBucket);
        }

        return $this->bucket;

    }

    /**
     * 寻找栈中最后一个运算符出现的位置 不包含 ()
     */
    private function searchLastOper()
    {
        try{
            $this->operatorBucket = array_values($this->operatorBucket);
            for ($i=count($this->operatorBucket) - 1; $i >=0 ; $i--) { 
                if(!in_array($this->operatorBucket[$i], [$this->left, $this->right])) {
                    return $this->operatorBucket[$i];
                }
            }
            return '';
        }catch(\Exception $e){
            var_dump($this->operatorBucket);die;
        }

    }
    
    /**
     * 寻找最后一个 ( 出现的位置
     * 
     * @param str string
     * @return
     */
    private function strLastKey($str)
    {
        for($i=count($this->operatorBucket) - 1; $i>=0; $i--) {
            if($this->operatorBucket[$i] == $str) {
                return $i;
            }
        }
        throw new \Exception("错误的表达式,()应该成对出现", 1);
        // return false;
    }
    
    /**
     * 运算符优先级
     */
    private function priority($operator='')
    {
        $data = [
            $this->operatorRide => 10, 
            $this->operatorExcept => 10,
            $this->operatorAdd => 5,
            $this->operatorReduce => 5,
            $this->left => 1,
            $this->right => 1
        ];
        if(!isset($data[$operator])) {
     
            throw new \Exception("错误的表达式!". $operator, 1);
            
        }
        return $data[$operator];
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值