php版本栈的应用中缀表达式求值

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

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值