初學者在實現「利用棧與佇列判斷回文」的經典練習時,對兩段核心代碼感到困惑:
while(!S.empty() && S.pop() == Q.dequeue()); 的具體執行邏輯與等價展開形式。return (ptr == NULL); 在 empty() 函式中的含義,以及為何不能簡寫為 return NULL;。程式定義了兩個類:Stack(鏈式棧)與 Queue(鏈式佇列),均基於同一結構體 list(含 data 與 next 指標)。主流程:
'.',同時推入棧 S 與佇列 Q。while(!S.empty() && S.pop() == Q.dequeue()) 逐對比較棧頂(後進先出)與佇列頭(先進先出)元素。while(!S.empty() && S.pop() == Q.dequeue()); 等價於什麼?這是一個帶副作用的條件判斷循環。由於 && 具有短路求值特性,其執行邏輯等價於:
while (true) {
if (S.empty()) break; // 棧空則結束,說明前面全匹配
int stackVal = S.pop(); // 彈出棧頂
int queueVal = Q.dequeue(); // 出隊佇列頭
if (stackVal != queueVal) break; // 不相等則提前結束
}
// 循環結束後,若 S.empty() 為真,則為回文
關鍵點:
S.pop() 與 Q.dequeue() 每次循環各執行一次,分別修改棧與佇列狀態。empty() 執行 6 次,pop()/dequeue() 各 4 次,說明輸入了 4 個有效字元(加上結束符 '.' 共 5 次檢查,最後一次 empty() 為真跳出)。pop() 與 dequeue() 未釋放節點記憶體(註釋掉了 delete),實際項目中必須補上,否則會洩漏。return (ptr == NULL); 為何不能寫成 return NULL;?int empty() 返回 int(0 或非 0 表示假/真)。ptr == NULL 是一個關係表達式,結果為 int:真為 1,假為 0,完美匹配返回類型。NULL 通常定義為 0 或 (void*)0。若返回 NULL,語法上雖可通過編譯(隱式轉為 0),但語義錯誤:
return NULL;意為「永遠返回假(0)」,導致empty()永遠判定棧非空,主循環邏輯崩潰。
正確寫法還可簡化為 return ptr == nullptr; (C++11) 或 return !ptr;,但必須保留比較邏輯。
pop() 与 dequeue() 中取消註釋 delete 釋放節點。pop()/dequeue() 應檢查空狀態,避免解引用空指標。std::stack、std::queue 及 std::string,避免手動管理鏈表節點。理解短路求值、副作用表達式與函式返回值語義,是看懂此類緊湊代碼的關鍵。建議初學者多練習將「單行技巧代碼」展開為「清晰的分支結構」,養成可讀、可維護的編程習慣。