首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 栈与队列回文判断代码深度解析:empty()、pop() 与三元运算符详解

     編輯:程式設計綜合問答

問題背景

初學者在實現「利用棧與佇列判斷回文」的經典練習時,對兩段核心代碼感到困惑:

  1. while(!S.empty() && S.pop() == Q.dequeue()); 的具體執行邏輯與等價展開形式。
  2. return (ptr == NULL); 在 empty() 函式中的含義,以及為何不能簡寫為 return NULL;。

代碼完整還原與結構說明

程式定義了兩個類:Stack(鏈式棧)與 Queue(鏈式佇列),均基於同一結構體 list(含 data 與 next 指標)。主流程:

  1. 讀取字元直到 '.',同時推入棧 S 與佇列 Q。
  2. 利用 while(!S.empty() && S.pop() == Q.dequeue()) 逐對比較棧頂(後進先出)與佇列頭(先進先出)元素。
  3. 若循環正常結束且棧為空,則輸入為回文。

核心疑點逐一拆解

1. 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),實際項目中必須補上,否則會洩漏。

2. 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;,但必須保留比較邏輯。

代碼改進建議

  1. 記憶體管理:在 pop() 与 dequeue() 中取消註釋 delete 釋放節點。
  2. 異常安全:pop()/dequeue() 應檢查空狀態,避免解引用空指標。
  3. 現代化重寫:生產代碼請直接使用 std::stack、std::queue 及 std::string,避免手動管理鏈表節點。

總結

理解短路求值、副作用表達式與函式返回值語義,是看懂此類緊湊代碼的關鍵。建議初學者多練習將「單行技巧代碼」展開為「清晰的分支結構」,養成可讀、可維護的編程習慣。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved