PHP 算法之 -- 计算器设计

 

<?php//$exp='300+20*6-20'; 
    $exp='71*2-50*3-3-67*6+80'; //14-15-3=-4
    //定义一个数栈和一个符号栈
    $numsStack=new MyStack();
    $operStack=new MyStack();
    $keepNum='';//专门用于拼接多位数的字符串
    $index=0;//$index就是一个扫描的标记
    while(true){
            //依次取出字符
            $ch=substr($exp,$index,1);
            //判断$ch是不是一个运算符号.
            if($operStack->isOper($ch)==true){
                //是运算符
                /**
                    3.如果发现是运算符
                    3.1 如果符号栈为空,就直接入符号栈
                    3.2. 如何符号栈,不为空,就判断
                    如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈.然后把当前符号入栈
                    3.3 如何符号栈,不为空,就判断
                    如果当前运算符的优先级大于符号栈顶的这个运算符的优先级,就入栈.
                */
                if($operStack->isEmpty()){
                        $operStack->push($ch);
                }else{
                        while(!$operStack->isEmpty() && $operStack->PRI($ch)<=$operStack->PRI($operStack->getTop())){                  
                                //从数栈依次出栈两个数.
                            $num1=$numsStack->pop();
                            $num2=$numsStack->pop();
                            //再从符号栈取出一个运算符
                            $oper=$operStack->pop();
                            //这里还需要一个计算的函数
                            $res=$operStack->getResult($num1,$num2,$oper);
                            //把$res入数栈<font size="" color=""></font>
                            $numsStack->push($res);
                        }
                        //把当前这个符号再入符号栈.//???????问题,一会在解决
                        $operStack->push($ch);            
                }
            }else{
                $keepNum.=$ch;                                
                //先判断是否已经到字符串最后.如果已经到最后,就直接入栈.
                if($index==strlen($exp)-1){
                    $numsStack->push($keepNum);
                }else{
                    //要判断一下$ch字符的下一个字符是数字还是符号.
                    if($operStack->isOper(substr($exp,$index+1,1))){                        
                        $numsStack->push($keepNum);
                        $keepNum='';
                    }
                }                   
            }
            $index++;//让$index指向下一个字符.
            //判断是否已经扫描完毕
            if($index==strlen($exp)){
                break;              
            }     
    }
    while(!$operStack->isEmpty()){
        
        $num1=$numsStack->pop();
        $num2=$numsStack->pop();
        $oper=$operStack->pop();
        $res=$operStack->getResult($num1,$num2,$oper);
        $numsStack->push($res);
    }

    //当退出while后,在数栈一定有一个数,这个数就是最后结果
    echo $exp.'='.$numsStack->getTop();
    //这是我们昨天写的一个栈.
    class MyStack{
            
            private $top=-1;//默认是-1,表示该栈是空的
            private $maxSize=5;//$maxSize表示栈最大容量
            private $stack=array();//


            //计算函数
            public function getResult($num1,$num2,$oper){
                
                $res=0;
                switch($oper){
                    case '+':
                        $res=$num1+$num2;
                    break;
                    case '-':
                        $res=$num2-$num1;
                    break;
                    case '*':
                        $res=$num1*$num2;
                    break;
                    case '/':
                        $res=$num2/$num1;
                    break;
                }

                return $res;
            }

            //返回栈顶的字符,只是取出,但是不出栈
            public function getTop(){
                return $this->stack[$this->top];
            }

            //判断优先级的函数
            public function PRI($ch){
                
                if($ch=='*'||$ch=='/'){
                    return 1;
                }else if($ch=='+'||$ch=='-'){
                    return 0;
                }
            }

            //判断栈是否为空
            public function isEmpty(){
                if($this->top==-1){
                    return TRUE;
                }else{
                    return FALSE;
                }
            }


            //增加一个函数[提示,在我们开发中,根据需要可以灵活的增加你需要的函数]
             //判断是不是一个运算符
             public function isOper($ch){
                
                if($ch=='-'||$ch=='+'||$ch=='*'||$ch=='/'){
                    return TRUE;
                }else{
                    return FALSE;
                }
             }

            //入栈的操作
            public function  push($val){
                //先判断栈是否已经满了
                if($this->top==$this->maxSize-1){
                    echo '<br/>栈满,不能添加';
                    return;
                }
                
                $this->top++;
                $this->stack[$this->top]=$val;


            }
        
            //出栈的操作,就是把栈顶的值取出
            public function pop(){

                //判断是否栈空
                if($this->top==-1){
                    echo '<br/>栈空';
                    return;
                }
                
                //把栈顶的值,取出
                $topVal=$this->stack[$this->top];
                $this->top--;
                return $topVal;

            }

            //显示栈的所有数据的方法.
            public function showStack(){
                
                if($this->top==-1){
                    echo '<br/>栈空';
                    return;
                }
                echo '<br/>当前栈的情况是....';
                for($i=$this->top;$i>-1;$i--){
                    echo '<br/> stack['.$i.']='.$this->stack[$i];
                }
            }
        }
?>
posted @ 2019-03-30 18:32  千载白云  阅读(357)  评论(0编辑  收藏  举报