zhan.php
<?php
//链表list
class linklist{
public $linknode;
public $size;
}
//链表节点
class linknode {
public $data;
public $next;
public function __construct($data) {
$this->data=$data;
$this->next=null;
}
}
//栈的类
class my_stack{
//初始化
public function init_stack(){
$lk = new linklist();
$header = new linknode(-1);
$lk->linknode = $header;
$lk->size=0;
return $lk;
}
//入栈
public function push_link($lk,$data){
//echo '11';exit;
$new_node = new linknode($data);
$new_node->next = $lk->linknode->next;
$lk->linknode->next=$new_node;
$lk->size++;
// return $lk;
}
//获取长度
public function get_size($lk)
{
return $lk->size;
}
//获得栈顶元素
//
public function get_top($lk)
{
$current = $lk->linknode->next;
return $current->data;
}
//出栈
public function pop_stack($lk)
{
$del_node = $lk->linknode->next;
$lk->linknode->next = $del_node->next;
$lk->size--;
$del_node=null;
}
}
/*
$stack = new my_stack();
//接受返回的链表
$lk=$stack->init_stack();
//入栈
$stack->push_link($lk,10);
$stack->push_link($lk,20);
$stack->push_link($lk,30);
//遍历 判断元素>0 然后获得栈顶元素,输出后 再弹出栈
while($stack->get_size($lk)>0){
$res= $stack->get_top($lk);
echo $res."<br />";
$stack->pop_stack($lk);
}
30
20
10
*/
?>
biaodashi.php
<?php
require_once("./zhan.php");
class biaodashi{
public function isleft($char)
{
return $char=="(";
}
public function isright($char)
{
return $char==")";
}
public function check($name,$stack,$lk){
$len = strlen($name);
//echo $len;
for($i=0;$i<$len;$i++)
{
//如果左括号压入栈
if($this->isleft($name[$i]))
{
$stack->push_link($lk,$name[$i]);
}
//如果右边括出栈 与左边括号相比
if($this->isright($name[$i]))
{
if($stack->get_size($lk)>0){
$stack->pop_stack($lk);
}else{
return 0;
}
}
}
if($stack->get_size($lk)>0)
{
return 0;
}else{
return 1;
}
}
//判断是否为数字
public function is_num($num)
{
if(preg_match('/(\d+)/is', $num)){
return 1;
}
else{
return 0;
}
}
//运算
public function yunsuan($a,$theta,$b)
{
$a = $a+0;
$b = $b+0;
echo $a,$theta,$b."<br/>";
switch ($theta) {
case '+':
return $a+$b;
break;
case '-':
return $a-$b;
break;
case '*':
return $a*$b;
break;
case '/':
if($b==0)
{
return 0;
}
return $a/$b;
break;
}
}
//运算符比较
/*$t1 是栈内的运算符
$t2 是本次获取字符的运算符
*/
public function bijiao($t1,$t2)
{
//echo $t1,$t2;
$f='';
switch($t2){
case "+":
if($t1=="(" || $t1=="#"){
$f="<";
}else{
$f=">";
}
break;
case "-":
if($t1=="(" || $t1=="#"){
$f="<";
}else{
$f=">";
}
break;
case "*":
if($t1=="(" || $t1=="#"||$t1=="+" || $t1=="-"){
$f="<";
}else{
$f=">";
}
break;
case "/":
if($t1=="(" || $t1=="#"||$t1=="+" || $t1=="-"){
$f="<";
}else{
$f=">";
}
break;
case "(":
if($t1==")")
{
$f="";
}else{
$f="<";
}
break;
case ")":
if($t1=="(")
{
$f="=";
}elseif($t1=="#"){
$f="";
}else{
$f=">";
}
break;
case "#":
if($t1=="#")
{
$f="=";
}elseif($t1=="("){
$f="";
}else{
$f=">";
}
//echo $f;
//exit($f);
//echo $f;
break;
}
return $f;
}
//获取表达式的值
public function get_val($str){
$str.='#';
$value=0;
//创建2个栈 一个数字栈 一个表达式栈
//操作数或者运算结果栈
$opnd = new my_stack();
$opnd_lk = $opnd->init_stack();
//运算符栈
$optr = new my_stack();
$optr_lk = $optr->init_stack();
//运算符栈 先押入一个#
$optr->push_link($optr_lk,"#");
//读取字符
$i=0;
$ch=$str[$i];
//echo $ch;exit;
while($ch!="#" || $optr->get_top($optr_lk) !="#")
{
//如果是数字直接进栈 读取下一个字符
if($this->is_num($ch)){
$opnd->push_link($opnd_lk,$ch);
$i++;
$ch=$str[$i];
}else{
//exit($ch);
//如果符号
//做运算符比较
$zhan_yunsuanfu=$optr->get_top($optr_lk);
//$optr->pop_stack($optr_lk);
$res=$this->bijiao($zhan_yunsuanfu,$ch);
//echo $res;exit;//5+(5*(6)+9/3*1)-(1+3)
switch ($res) {
case '<':
//当前字符押入栈,读取下一个ch
$optr->push_link($optr_lk,$ch);
$i++;
$ch=$str[$i];
break;
case '>':
//echo "aaaaa";
//弹出字符栈顶的运算符运算,并将结果押入数字栈里
//先获取运算符 再弹出
$theta = $optr->get_top($optr_lk);
$optr->pop_stack($optr_lk);
//先获取运算符 再弹出 因为栈的顺序是反的 所以先出来的 赋值给b 也就是第二个数字 最后出来的才是第一个 赋值给a
$b=$opnd->get_top($opnd_lk);
$opnd->pop_stack($opnd_lk);
$a=$opnd->get_top($opnd_lk);
$opnd->pop_stack($opnd_lk);
//计算结果
$yusuan_num =$this->yunsuan($a,$theta,$b);
//echo $yusuan_num."<br />";exit;
//重新押入栈
$opnd->push_link($opnd_lk,$yusuan_num);
break;
case '=':
//一般这种情况是左右两边括号相等 这时候弹出括号 并且继续读取下一个字符就可以了
$optr->pop_stack($optr_lk);
$i++;
$ch=$str[$i];
break;
}
}
//echo $ch;
}
//循环结束后弹出数字栈的 栈顶元素
$value=$opnd->get_top($opnd_lk);
//echo $value;exit;
$opnd->pop_stack($opnd_lk);
return $value;
}
}
//创建一个检测栈
$stack = new my_stack();
//接受返回的链表
$lk=$stack->init_stack();
$str = "5+(5*(6)+9/3*1)-(1+3)";
$biaodashi = new biaodashi();
$ok=$biaodashi->check($str,$stack,$lk);
if(!$ok)
{
exit("表达式不正确!");
}
$value=$biaodashi->get_val($str);
echo $value;
参考b站2个老师的讲解 https://www.bilibili.com/video/BV1GV411f727?t=483
https://www.bilibili.com/video/BV1yE411p7fD?t=2448