當數據元素爲類類型,StaticQueue 的對象在建立時會屢次調用元素類型的構造函數,影響效率!node
文件:main.cppios
#include <iostream> #include "StaticQueue.h" using namespace std; using namespace DTLib; class Test : public Object { public: Test() { cout << "Test()" << endl; } ~Test() { cout << "~Test()" << endl; } }; int main() { StaticQueue<Test, 5> queue; cout << "queue.length() = " << queue.length() << endl; return 0; }
輸出:編程
Test() Test() Test() Test() Test() queue.length() = 0 ~Test() ~Test() ~Test() ~Test() ~Test()
- 類模板,抽象父類 Queue 的直接子類
- 在內部使用鏈式結構實現元素的存儲
- 只在鏈表的頭部和尾部進行操做
文件:LinkQueue.hide
#ifndef LINKQUEUE_H #define LINKQUEUE_H #include "Queue.h" #include "LinkList.h" #include "Exception.h" namespace DTLib { template <typename T> class LinkQueue : public Queue<T> { public: LinkQueue() = default; void add(const T &e) override // O(n) { m_list.insert(e); } void remove() override // O(1) { if (m_list.length() > 0) { m_list.remove(0); } else { THROW_EXCEPTION(InvalidOpertionExcetion, "No element in current StaticQueue ..."); } } T front() const override // O(1) { if (m_list.length() > 0) { return m_list.get(0); } else { THROW_EXCEPTION(InvalidOpertionExcetion, "No element in current StaticQueue ..."); } } void clear() override // O(n) { m_list.clear(); } int length() const override // O(1) { return m_list.length(); } ~LinkQueue() // O(n) { clear(); } protected: LinkList<T> m_list; }; } #endif // LINKQUEUE_H
文件:main.cpp函數
#include <iostream> #include "LinkQueue.h" using namespace std; using namespace DTLib; class Test : public Object { public: Test() { cout << "Test()" << endl; } ~Test() { cout << "~Test()" << endl; } }; int main() { LinkQueue<Test> queue_t; cout << "-----" << endl; LinkQueue<int> queue; for (int i=0; i<5; ++i) { queue.add(i); } while (queue.length() > 0) { cout << queue.front() << endl; queue.remove(); } return 0; }
輸出:優化
----- 0 1 2 3 4
問題:使用 LinkList 類實現鏈表式隊列是否合適?是否有更好的方案?
void add(const T &e) override // O(n) { m_list.insert(e); }
每次插入新元素,都須要遍歷整個鏈表到尾部!!spa
文件:LinkQueue.h設計
#ifndef LINKQUEUE_H #define LINKQUEUE_H #include "Queue.h" #include "LinuxList.h" #include "Exception.h" namespace DTLib { template <typename T> class LinkQueue : public Queue<T> { public: LinkQueue() { m_length = 0; INIT_LIST_HEAD(&m_header); } void add(const T &e) override // O(1) { Node *node = new Node; if (node != nullptr) { node->value = e; list_add_tail(&node->head, &m_header); ++m_length; } else { THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory to add element ..."); } } void remove() override // O(1) { if (m_length > 0) { list_head *toDel = m_header.next; list_del(toDel); --m_length; delete list_entry(toDel, Node, head); } else { THROW_EXCEPTION(InvalidOpertionExcetion, "No element in current LinkQueue ..."); } } T front() const override // O(1) { if (m_length > 0) { return list_entry(m_header.next, Node, head)->value; } else { THROW_EXCEPTION(InvalidOpertionExcetion, "No element in current LinkQueue ..."); } } void clear() override // O(n) { while (m_length > 0) { remove(); } } int length() const override // O(1) { return m_length; } ~LinkQueue() // O(n) { clear(); } protected: struct Node : public Object { list_head head; T value; }; list_head m_header; int m_length; }; } #endif // LINKQUEUE_H
文件:main.cppcode
#include <iostream> #include "LinkQueue.h" using namespace std; using namespace DTLib; class Test : public Object { public: Test() { cout << "Test()" << endl; } ~Test() { cout << "~Test()" << endl; } }; int main() { LinkQueue<Test> queue_t; cout << "-----" << endl; LinkQueue<int> queue; for (int i=0; i<5; ++i) { queue.add(i); } while (queue.length() > 0) { cout << queue.front() << endl; queue.remove(); } return 0; }
輸出:對象
----- 0 1 2 3 4
- SaticQueue 在初始化時可能屢次調用元素類型的構造函數
- LinkList 的組合使用實現了隊列的功能,可是不夠高效
- LinkQueue 的最終實現組合使用了 Linux 內核鏈表
- LinkQueue 中入隊和出隊操做能夠在常量時間內完成
以上內容整理於狄泰軟件學院系列課程,請你們保護原創!