PHP栈的定义、入栈出栈方法及基于堆栈实现的计算器完整实例

 更新时间:2017年11月01日 11:19:35   转载 作者:binbin1129  
这篇文章主要介绍了PHP栈的定义、入栈出栈方法及基于堆栈实现的计算器,结合实例形式较为详细的分析了php定义与使用栈的基本方法,并结合完整实例形式给出了php基于堆栈实现高级计算器功能的相关操作技巧,需要的朋友可以参考下

本文实例讲述了PHP栈的定义、入栈出栈方法及基于堆栈实现的计算器。分享给大家供大家参考,具体如下:

栈是线性表的一种,他的特点是后入先出,可以这么理解,栈就像一个存东西的盒子,先放进去的在最底层,后放进去的在上层,因为上层的东西把底层的东西压住了,下层的想要出去就必须把上层的先拿开才行。

介绍代码:

data类:就是存放数据的类。()就是要放入栈的东西
stack类:是栈的类,整个对栈就在这个类中

主要方法:

入栈push_stack($data)检测栈是否已满,如果没满就让数据入栈。
出栈pop_stack($data)检测栈是否为空,如果不空可以出栈
读取栈顶元素top_stack()如果栈不空,返回当前栈顶部的数据。

下边是代码:

<?php
/**
* Author Been
**/
class data{
  //数据
  private $data;
  public function __construct($data){
    $this->data=$data;
    echo $data.":哥入栈了!<br>";
  }
  public function getData(){
    return $this->data;
  }
  public function __destruct(){
    echo $this->data.":哥走了!<br>";
  }
}
class stack{
  private $size;
  private $top;
  private $stack=array();
  public function __construct($size){
    $this->Init_Stack($size);
  }
  //初始化栈
  public function Init_Stack($size){
    $this->size=$size;
    $this->top=-1;
  }
  //判断栈是否为空
  public function Empty_Stack(){
    if($this->top==-1)return 1;
    else return 0;
  }
  //判断栈是否已满
  public function Full_Stack(){
    if($this->top<$this->size-1)return 0;
    else return 1;
  }
  //入栈
  public function Push_Stack($data){
    if($this->Full_Stack())echo "栈满了<br />";
    else $this->stack[++$this->top]=new data($data);
  }
  //出栈
  public function Pop_Stack(){
    if($this->Empty_Stack())echo "栈空着呢<br />";
    else unset($this->stack[$this->top--]);
  }
  //读取栈顶元素
  public function Top_Stack(){
    return $this->Empty_Stack()?"栈空无数据!":$this->stack[$this->top]->getData();
  }
}
$stack=new stack(4);
$stack->Pop_Stack();
$stack->Push_Stack("aa");
$stack->Push_Stack("aa1");
$stack->Pop_Stack("aa1");
$stack->Push_Stack("aa2");
$stack->Push_Stack("aa3");
$stack->Push_Stack("aa4");
echo $stack->Top_Stack(),'<br />';
$stack->Push_Stack("aa5");
$stack->Push_Stack("aa6");
$stack->Pop_Stack();
$stack->Pop_Stack();
$stack->Pop_Stack();
$stack->Pop_Stack();
$stack->Pop_Stack();
$stack->Pop_Stack();

运行结果:

栈空着呢
aa:哥入栈了!
aa1:哥入栈了!
aa1:哥走了!
aa2:哥入栈了!
aa3:哥入栈了!
aa4:哥入栈了!
aa4
栈满了
栈满了
aa4:哥走了!
aa3:哥走了!
aa2:哥走了!
aa:哥走了!
栈空着呢
栈空着呢

案例:基于堆栈的高级计算器

当我们得到一个字符串运算式该如何去得出它的运算结果呢?

这时候我们就能使用堆栈的算法很巧妙的解决这个问题。

思路是这样的:(我们利用php函数substr循环去截取这个字符串运算式,依次取出这个字符串的值【我们得从第一个字符开始截取】,我们将开始截取位置设为一个循环增长的变量,初始化为【$index=0】),同时还需要创建两个栈,一个专门存放数字【$numStack】,一个存放运算符【$operStack】,我们还需要一个可以判断是否是运算符号的函数,将每次截取的值放入这个自定义函数中,返回一个可以区别为数字或运算符的标识,通过对这个标识的判断确定值是数字还是运算符,是数字就插入数栈,是运算符的话就插入符号栈。插入数栈的话可直接插入,但是符号栈的话需要特殊处理一下[【如果符号栈为空则直接插入,不为空:我们要将插入的符号与栈内的符号进行运算优先级比较(可以定义一个函数来判定符号优先级,把 *  和 / 假定为1  把 + 和 - 假定为0  假设数字大的优先级高,如此就能得出运算符优先级),当待插入的符号优先级小于等于栈内顶端的运算符优先级,就从数栈弹出两个值  符号栈弹出一个运算符 将它们进行运算】

下面是一个php的实例【参考自韩顺平老师的php算法教程】

<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8'/>
</head>
<h1>高级计算器</h1>
<?php
/**
 * 一个栈类
 */
class MyStack{
      public $top=-1;//默认是-1,表示该栈是空的
      public $maxSize=15;//$maxSize表示栈最大容量
      public $stack=array();//
      //入栈的操作
      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/>栈空1';
          return;
        }
        //把栈顶的值,取出
        $topVal=$this->stack[$this->top];
        $this->top--;
        return $topVal;
      }
      //显示栈的所有数据的方法.
      public function showStack()
      {
        if($this->top==-1){
          echo '<br/>栈空2';
          return;
        }
        echo '<br/>当前栈的情况是....';
        for($i=$this->top;$i>-1;$i--){
          echo '<br/> stack['.$i.']='.$this->stack[$i];
        }
      }
      //判断是否是一个运算符
      public function isOper($val)
      {
        if ($val=='+'||$val=='-'||$val=='*'||$val=='/')
        {
          return true;
        }
      }
      //判断栈是否为空
      public function isEmpty()
      {
        if ($this->top==-1) return true;
      }
      /**
       * 比较运算符的优先级
       * 我把 * 和/运算符的优先级看作1
       * +和- 看作0
       * 通过它们之间的比较就能得出它们的优先级谁更高
       */
      public function PRI($oper)
      {
        if ($oper=='*'||$oper=='/')
        {
          return 1;
        } else if ($oper=='+'||$oper=='-') {
          return 0;
        }
      }
      //返回栈顶端的值
      public function getTop()
      {
        return $this->stack[$this->top];
      }
      //计算
      public function getResult($num1,$num2,$oper)
      {
        switch ($oper)
        {
          case '+':
            $res = $num2+$num1;
          break;
          case '-':
            $res = $num2-$num1;
          break;
          case '*':
            $res = $num2*$num1;
          break;
          case '/':
            $res = $num2/$num1;
          break;
        }
        return $res;
      }
}
//需要进行运算的表达式
$str = '12+5*2+3-5*2';
//字符串的指针
$index = 0;
//声明一个用于组合联系数字的变量
$keepNum = '';
//定义一个数栈和一个符号栈
$numsStack=new MyStack();
$operStack=new MyStack();
while (true)
{
  $val = mb_substr($str,$index,1);
  //如果是一个符号就入符号栈 否则入数栈
  if ($operStack->isOper($val)==true)
  {
    //符号入栈前需要判断一下 栈为空直接入栈 不为空需要比较当前运算符与栈顶端的运算符
    //如果当前运算符的优先级低于栈内的 则需要运算
    if ($operStack->isEmpty())
    {
      $operStack->push($val);
    } else {
       while (!$operStack->isEmpty()&&$operStack->PRI($val)<=$operStack->PRI($operStack->getTop()))
       {
         //当前符号的优先级要直到高于栈内的时候才能入栈 否则要计算
        //当前运算符的优先级低于栈内的 则运算
        $num1 = $numsStack->pop();
        $num2 = $numsStack->pop();
        $oper = $operStack->pop();
        $res = $numsStack->getResult($num1,$num2,$oper);
        //计算完毕将结果入栈
        $numsStack->push($res);
       }
      //把当前这个符号再入符号栈
      $operStack->push($val);
        }
  } else {
    //考虑如果是连续数字的问题
    $keepNum.=$val;
    //先判断是否已经到字符串最后.如果已经到最后,就直接入栈.
    if ($index==mb_strlen($str)-1)
    {
      $numsStack->push($keepNum);//是数字直接入栈
    } else {
      //要判断一下$ch字符的下一个字符是数字还是符号.
      if ($operStack->isOper(mb_substr($str,$index+1,1)))
      {
        $numsStack->push($keepNum);
        $keepNum='';
      }
    }
  }
  $index++;//让$index指向下一个字符.
  if ($index==mb_strlen($str)) break;//已扫描到字符串的末尾 就退出while循环
}
/*
4. 当扫描完毕后,就依次弹出数栈和符号栈的数据,并计算,最终留在数栈的值,就是运算结果,只有符号栈不空就一直计算
*/
while (!$operStack->isEmpty())
{
  $num1 = $numsStack->pop();
  $num2 = $numsStack->pop();
  $oper = $operStack->pop();
  $res = $numsStack->getResult($num1,$num2,$oper);
  //计算完毕将结果入栈
  $numsStack->push($res);
}
//当退出while后,在数栈一定有一个数,这个数就是最后结果
echo $str.'='.$numsStack->getTop();
?>

运行结果:

12+5*2+3-5*2=15

PS:这里再为大家推荐几款计算工具供大家进一步参考借鉴:

在线一元函数(方程)求解计算工具:
http://tools.jb51.net/jisuanqi/equ_jisuanqi

科学计算器在线使用_高级计算器在线计算:
http://tools.jb51.net/jisuanqi/jsqkexue

在线计算器_标准计算器:
http://tools.jb51.net/jisuanqi/jsq

更多关于PHP相关内容感兴趣的读者可查看本站专题:《PHP数学运算技巧总结》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《PHP数组(Array)操作技巧大全》、《PHP数据结构与算法教程》、《php程序设计算法总结》及《php正则表达式用法总结

希望本文所述对大家PHP程序设计有所帮助。

相关文章

  • PHP中字符安全过滤函数使用小结

    PHP中字符安全过滤函数使用小结

    这篇文章主要简单介绍了PHP中字符安全过滤函数,对于防止sql注入攻击XSS攻击能非常有用,这里推荐给大家。
    2015-02-02
  • PHP实现批量修改文件后缀名的方法

    PHP实现批量修改文件后缀名的方法

    这篇文章主要介绍了PHP实现批量修改文件后缀名的方法,涉及php针对文件的递归遍历及重命名的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • PHP清除数组中所有字符串两端空格的方法

    PHP清除数组中所有字符串两端空格的方法

    这篇文章主要介绍了PHP清除数组中所有字符串两端空格的方法,主要涉及对PHP数组的操作以及字符串操作,非常具有实用价值,需要的朋友可以参考下
    2014-10-10
  • PHP中类的继承和用法实例分析

    PHP中类的继承和用法实例分析

    这篇文章主要介绍了PHP中类的继承和用法,较为详细的分析了php中类的继承方法、使用方法与相关注意事项,需要的朋友可以参考下
    2016-05-05
  • php压缩文件夹最新版

    php压缩文件夹最新版

    这篇文章主要为大家详细介绍了php压缩文件夹的最新版代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • 利用PHP判断是否是连乘数字串的方法示例

    利用PHP判断是否是连乘数字串的方法示例

    这篇文章主要介绍了利用PHP判断是否是连乘数字串的方法示例,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面跟着小编一起来学习学习吧。
    2017-07-07
  • php中实现获取随机数组列表的自定义函数

    php中实现获取随机数组列表的自定义函数

    这篇文章主要介绍了php中实现获取随机数组列表的自定义函数,本文直接给出实现代码,需要的朋友可以参考下
    2015-04-04
  • php文件上传你必须知道的几点

    php文件上传你必须知道的几点

    这篇文章主要介绍了php文件上传你必须知道的几点,只有真正的理解了这些知识点,打好基础,才能熟练掌握php文件上传功能的实现。
    2015-10-10
  • PHP实现函数内修改外部变量值的方法示例

    PHP实现函数内修改外部变量值的方法示例

    这篇文章主要介绍了PHP实现函数内修改外部变量值的方法,涉及php全局变量、传值调用、引用等相关操作技巧,需要的朋友可以参考下
    2018-12-12
  • php通过session防url攻击方法

    php通过session防url攻击方法

    这篇文章主要介绍了php通过session防url攻击方法,可通过session获取用户名再传入URL来防止URL攻击,是非常实用的技巧,需要的朋友可以参考下
    2014-12-12

最新评论