本篇內容介紹了“如何用Linux內核鏈表來實現DTLib中的雙向循環鏈表”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
創新互聯建站專注于蓬萊網站建設服務及定制,我們擁有豐富的企業做網站經驗。 熱誠為您提供蓬萊營銷型網站建設,蓬萊網站制作、蓬萊網頁設計、蓬萊網站官網定制、小程序開發服務,打造蓬萊網絡公司原創品牌,更為您提供蓬萊網站排名全網營銷落地服務。繼承關系如下圖所示
下來我們來講講它的設計思路:數據結點之間在邏輯上構成雙向循環鏈表,頭結點僅用于結點的定位。如下圖所示
實現思路:
1、通過模板定義 DualCircleList 類。繼承自 DualLinkList 類;
2、在 DualCircleList 內部使用 Linux 內核鏈表進行實現;
3、使用 struct list_head 定義 DualCircleList 的頭結點;
4、特殊處理:循環遍歷時忽略頭結點
實現要點:
1、通過 list_head 進行目標結點定位(position(i));
2、通過 list_entry 將 list_head 指針轉換為目標結點指針;
3、通過 list_for_each 實現 int find(const T& e) 函數;
4、遍歷函數中的 next() 和 pre() 需要考慮跳過頭結點
下來我們來看看基于 Linux 內核鏈表的雙向循環鏈表是怎樣寫的
DualCircleList 源碼
#ifndef DUALCIRCLELIST_H #define DUALCIRCLELIST_H #include "DualLinkList.h" #include "LinuxList.h" namespace DTLib { template < typename T > class DualCircleList : public DualLinkList<T> { protected: struct Node : public Object { list_head head; T value; }; list_head m_header; list_head* m_current; list_head* position(int i) const { list_head* ret = const_cast<list_head*>(&m_header); for(int p=0; p<i; p++) { ret = ret->next; } return ret; } int mod(int i) const { return (this->m_length == 0) ? 0 : (i % this->m_length); } public: DualCircleList() { this->m_length = 0; this->m_step = 1; m_current = NULL; INIT_LIST_HEAD(&m_header); } bool insert(const T& e) { return insert(this->m_length, e); } bool insert(int i, const T& e) { bool ret = true; Node* node = new Node(); i = i % (this->m_length + 1); if(node != NULL) { node->value = e; list_add_tail(&node->head, position(i)->next); this->m_length++; } else { THROW_EXCEPTION(NoEnoughMemoryException, "No memory to insert new element ..."); } return ret; } bool remove(int i) { bool ret = true; i = mod(i); ret = ((0 <= i) && (i < this->m_length)); if( ret ) { list_head* toDel = position(i)->next; if( m_current == toDel ) { m_current = toDel->next; } list_del(toDel); this->m_length--; delete list_entry(toDel, Node, head); } return ret; } bool set(int i, const T& e) { bool ret = true; i = mod(i); ret = ((0 <= i) && (i < this->m_length)); if( ret ) { list_entry(position(i)->next, Node, head)->value = e; } return ret; } T get(int i) const { T ret; if( get(i, ret) ) { return ret; } else { THROW_EXCEPTION(IndexOutOfBoundsException, "Invaild parameter i to get element ..."); } } bool get(int i, T& e) const { bool ret = true; i = mod(i); ret = ((0 <= i) && (i < this->m_length)); if( ret ) { e = list_entry(position(i)->next, Node, head)->value; } return ret; } int find(const T& e) const { int ret = -1; int i = 0; list_head* slider = NULL; list_for_each(slider, &m_header) { if( list_entry(slider, Node, head)->value == e ) { ret = i; break; } i++; } return ret; } int length() const { return this->m_length; } void clear() { while( this->m_length > 0 ) { remove(0); } } bool move(int i, int step = 1) { bool ret = (step > 0); i = mod(i); ret = ret && ((0 <= i) && (i < this->m_length)); if( ret ) { m_current = position(i)->next; this->m_step = step; } return ret; } bool end() { return (m_current == NULL) || (this->m_length == 0); } T current() { if( !end() ) { return list_entry(m_current, Node, head)->value; } else { THROW_EXCEPTION(INvalidOPerationException, "No value at current position ..."); } } bool next() { int i = 0; while( (i < this->m_step) && !end() ) { if( m_current != &m_header ) { m_current = m_current->next; i++; } else { m_current = m_current->next; } } if( m_current == &m_header ) { m_current = m_current->next; } return (i == this->m_step); } bool pre() { int i =0; while( (i < this->m_step) && !end() ) { if( m_current != &m_header ) { m_current = m_current->next; i++; } else { m_current = m_current->prev; } } if( m_current == &m_header ) { m_current = m_current->next; } return (i == this->m_step); } ~DualCircleList() { clear(); } }; } #endif // DUALCIRCLELIST_H
下來我們寫點測試代碼看看上面的代碼有沒有問題
main.cpp 源碼
#include <iostream> #include "DualCircleList.h" using namespace std; using namespace DTLib; int main() { DualCircleList<int> d1; for(int i=0; i<5; i++) { d1.insert(0, i); d1.insert(0, 5); } cout << "begin" << endl; d1.move(d1.length()-1); while( d1.find(5) != -1 ) { if( d1.current() == 5 ) { cout << d1.current() << endl; d1.remove(d1.find(d1.current())); } else { d1.pre(); } } cout << "end" << endl; for(int i=0; i<d1.length(); i++) { cout << d1.get(i) << endl; } return 0; }
我們先來分析下,在插入 i 后,隨后便插入 5。先打印出 5 個 5,隨后刪除這 5 個數,然后在打印出剩下的 4 ~ 0。看看結果是否如我們所分析的那樣
“如何用Linux內核鏈表來實現DTLib中的雙向循環鏈表”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注創新互聯網站,小編將為大家輸出更多高質量的實用文章!
另外有需要云服務器可以了解下創新互聯scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業上云的綜合解決方案,具有“安全穩定、簡單易用、服務可用性高、性價比高”等特點與優勢,專為企業上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。
分享名稱:如何用Linux內核鏈表來實現DTLib中的雙向循環鏈表-創新互聯
當前地址:http://vcdvsql.cn/article6/dsdcig.html
成都網站建設公司_創新互聯,為您提供電子商務、外貿建站、網站導航、域名注冊、網站維護、全網營銷推廣
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯