棧和隊列和以前講到的實戰PHP數據結構基礎之雙鏈表 同樣都是線性結構。git
棧遵循後進先出的原則(LIFO)。這意味着棧只有一個出口用來壓入元素和彈出元素,當咱們執行壓入或者彈出操做的時候要注意棧是否已滿或者棧是不是空的。github
仍是廢話很少說,直接來看咱們對棧執行的經常使用操做。web
首先咱們定義一個StackInterface。算法
interface StackInterface {
public function push(string $item);
public function pop();
public function top();
public function isEmpty();
}
複製代碼
來看基於數組的棧實現express
class ArrStack implements StackInterface {
private $stack;
private $limit;
public function __construct(int $limit = 20) {
$this->limit = $limit;
$this->stack = [];
}
public function __get($val) {
return $this->$val;
}
public function push(string $data = null) {
if (count($this->stack) < $this->limit) {
array_push($this->stack, $data);
} else {
throw new \OverflowException('stack is overflow');
}
}
public function pop() {
if ($this->isEmpty()) {
throw new \UnderflowException('stack is empty');
} else {
return array_pop($this->stack);
}
}
public function isEmpty() {
return empty($this->stack);
}
public function top() {
return end($this->stack);
}
複製代碼
得益於PHP強大的array結構,咱們垂手可得的寫出來了棧的基本操做方法。果真世界上最好的語言名不虛傳。數組
那有同窗說了,你說棧和以前的鏈表都是線性結構,那可不能夠直接使用鏈表實現棧呢?這個問題很是犀利啊,答案是能夠的。bash
可能機智的同窗已經猜到了,我以前已經定義了一個棧接口,那棧的實現確定不止只有上面一種哈。來看基於鏈表的實現。數據結構
class LinkedListStack implements StackInterface {
private $stack;
private $limit;
public function __construct(int $limit) {
$this->limit = $limit;
$this->stack = new LinkedList();
}
public function top() {
return $this->stack->getNthNode($this->stack->getSize() - 1)->data;
}
public function isEmpty() {
return $this->stack->getSize() === 0;
}
public function pop() {
if ($this->isEmpty()) {
throw new \UnderflowException('stack is empty');
} else {
$lastItem = $this->top();
$this->stack->deleteLast();
return $lastItem;
}
}
public function push(string $item) {
if ($this->stack->getSize() < $this->limit) {
$this->stack->insert($item);
} else {
throw new \OverflowException('stack is overflow');
}
}
複製代碼
裏面涉及到了以前的鏈表實現,不瞭解細節的同窗能夠去這裏看看。有同窗又問,那棧到底有什麼用處?這個問題很是好,來看一個需求。數據結構和算法
請實現一個數學表達式檢查類,輸入一個下面表達式,預期結果爲true。優化
"8 * (9 -2) + { (4 * 5) / ( 2 * 2) } 複製代碼
下面的爲false。
"5 * 8 * 9 / ( 3 * 2 ) )"
複製代碼
下面的也爲false。
"[{ (2 * 7) + ( 15 - 3) ]"
複製代碼
本身想一下,再往下看實現。
class ExpressionChecker {
//$expressions[] = "8 * (9 -2) + { (4 * 5) / ( 2 * 2) }";
//$expressions[] = "5 * 8 * 9 / ( 3 * 2 ) )";
//$expressions[] = "[{ (2 * 7) + ( 15 - 3) ]";
public function check(string $expression): bool {
$stack = new \SplStack();
foreach (str_split($expression) as $item) {
switch ($item) {
case '{':
case '[':
case '(':
$stack->push($item);
break;
case '}':
case ']':
case ')':
if ($stack->isEmpty()) return false;
$last = $stack->pop();
if (
$item == '{' && $last != '}' ||
$item == '(' && $last != ')' ||
$item == '[' && $last != ']'
)
return false;
break;
}
}
if ($stack->isEmpty()) {
return true;
}
return false;
}
}
複製代碼
PHP基礎數據結構專題系列目錄地址:github.com/... 主要使用PHP語法總結基礎的數據結構和算法。還有咱們平常PHP開發中容易忽略的基礎知識和現代PHP開發中關於規範、部署、優化的一些實戰性建議,同時還有對Javascript語言特色的深刻研究。