采用鏈式存儲的棧成為鏈式棧(或簡稱鏈棧), 鏈棧的優點是便於多個棧共享存儲空間和提高其效率, 且不存在棧滿上溢的情況(因為鏈棧是靠指針鏈接到一起,只要內存夠大, 則鏈棧理論上可以存儲的元素是沒有上限的);
與順序棧相比, 由於順序棧是采用的數組實現, 因此一旦數組填滿, 則必須重新申請內存, 並將所有元素”搬家”, 而鏈棧則省略了這一”耗時耗力”的工作, 但卻需要付出附加一個指針的代價;
鏈棧通常采用單鏈表實現, 並規定所有的操作都必須實在單鏈表的表頭進行, 而且w我們的鏈棧沒有頭結點, m_top直接指向棧頂元素;
鏈式棧的圖示如下:
鏈棧節點構造:
templateclass ChainNode { template friend ostream &operator<<(ostream &os, const LinkStack &stack); friend class LinkStack ; private: ChainNode(const Type &_data, ChainNode *_next = NULL) :data(_data), next(_next) {} Type data; ChainNode *next; };
鏈棧設計:
templateclass LinkStack { template friend ostream &operator<<(ostream &os, const LinkStack &stack); public: LinkStack(): m_top(NULL) {} ~LinkStack() { makeEmpty(); } bool isEmpty() const { return m_top == NULL; } void pop() throw(std::out_of_range); const Type &top() const throw(std::out_of_range); void push(const Type &data); void makeEmpty(); private: ChainNode *m_top; };
棧的三大操作:
templateconst Type &LinkStack ::top() const throw (std::out_of_range) { if (isEmpty()) throw std::out_of_range("stack is empty, can`t get data"); return m_top->data; }
templatevoid LinkStack ::pop() throw (std::out_of_range) { if (isEmpty()) throw std::out_of_range("stack is empty, can`t delete"); ChainNode *deleteNode = m_top; m_top = m_top->next; delete deleteNode; }
templatevoid LinkStack ::push(const Type &data) { //此處是整個鏈棧的關鍵點 // 該操作會生成一個節點, // 並自動將m_top上移一格, // 而且將m_top原先指向的節點, 作為新生成的節點的下一節點 //注意此處 //如果第一次運行push, 則原m_top為NULL // 新m_top指向第一個元素 m_top = new ChainNode (data, m_top); }
清空整個棧:
templatevoid LinkStack ::makeEmpty() { while (!isEmpty()) { pop(); } }
輸出棧內所有內容:
templateostream &operator<<(ostream &os, const LinkStack &stack) { ChainNode *currentNode = stack.m_top; while (currentNode != NULL) { cout << currentNode->data << ' '; currentNode = currentNode->next; } return os; }
測試代碼:
int main() { LinkStacktest; for (int i = 0; i < 10; ++i) { test.push(rand()%100); } cout << test << endl; cout << "top = " << test.top() << endl; test.pop(); cout << "top = " << test.top() << endl; test.push(1); cout << "top = " << test.top() << endl; while (!test.isEmpty()) { test.pop(); } cout << test << endl; test.push(11); test.push(22); test.push(33); cout << test << endl; test.makeEmpty(); try { cout << "top = " << test.top() << endl; } catch (const std::exception &e) { cerr << e.what() << endl; } return 0; }