DualLinkList
生活随笔
收集整理的這篇文章主要介紹了
DualLinkList
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- 1 單鏈表的缺陷
- 2 雙向鏈表的實(shí)現(xiàn)
- 2.1 設(shè)計(jì)思路
- 2.2 雙向鏈表的繼承層次結(jié)構(gòu)
- 2.3 DualLinkList的定義
- 2.4 雙向鏈表的特點(diǎn)
- 3 代碼實(shí)現(xiàn)
- 4 開放性問題
1 單鏈表的缺陷
單鏈表具有單向性,只能從頭結(jié)點(diǎn)開始高效訪問鏈表中的數(shù)據(jù)元素。
缺陷: 如果需要逆向訪問單鏈表中的數(shù)據(jù)元素將極其低效。
2 雙向鏈表的實(shí)現(xiàn)
2.1 設(shè)計(jì)思路
在單鏈表的結(jié)點(diǎn)中增加一個(gè)指針pre,用于指向當(dāng)前結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)。
2.2 雙向鏈表的繼承層次結(jié)構(gòu)
2.3 DualLinkList的定義
2.4 雙向鏈表的特點(diǎn)
- 雙向鏈表是為了彌補(bǔ)單鏈表的缺陷而重新設(shè)計(jì)的。
- 在概念上,雙向鏈表不是單鏈表,沒有繼承關(guān)系。
- 雙向鏈表中的游標(biāo)能夠直接訪問當(dāng)前結(jié)點(diǎn)的前驅(qū)和后繼。
- 雙向鏈表是線性表的最終實(shí)現(xiàn)(更貼近理論上的線性表)。
3 代碼實(shí)現(xiàn)
DualLinkList.h
#ifndef DUALLINKLIST_H #define DUALLINKLIST_H#include "List.h" #include "Exception.h"namespace LemonLib { template < typename T > class DualLinkList : public List<T> { protected:struct Node : public Object{T value;Node* next;Node* pre;};/* 注意:當(dāng)前結(jié)構(gòu)體必須繼承自O(shè)bject類,否則會(huì)導(dǎo)致和Node的內(nèi)存布局不同,直接拋出異常 */mutable struct : public Object{char reserved[sizeof(T)];Node* next;Node* pre;}m_header;int m_length;Node* m_current;int m_step;Node* position(int index) const{Node* ret = reinterpret_cast<Node*>(&m_header);for (int i=0; i<index; i++){ret = ret->next;}return ret;}virtual Node* create(){return new Node();}virtual void destroy(Node* pn){delete pn;} public:DualLinkList(){m_header.next = NULL;m_header.pre = NULL;m_length = 0;m_current = NULL;m_step = 0;}bool insert(int index, const T& e){bool ret = (0 <= index) && (index <= m_length);if (ret){Node* node = create();if (node != NULL){Node* current = position(index);Node* next = current->next;node->value = e;node->next = next; // 當(dāng)前結(jié)點(diǎn)的next指針指向下一個(gè)結(jié)點(diǎn)current->next = node;if (current != reinterpret_cast<Node*>(&m_header)) // 當(dāng)前插入的位置不是首結(jié)點(diǎn){node->pre = current;}else{node->pre = NULL;}if (next != NULL) // 當(dāng)前插入的不是最后一個(gè)結(jié)點(diǎn){next->pre = node;}m_length++;}else{THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory to inset element ...");}}return ret;}bool insert(const T& e)// 插入到尾部{return insert(m_length, e);}bool remove(int index){bool ret = (0 <= index) && (index < m_length);if (ret){Node* current = position(index);Node* toDel = current->next;Node* next = toDel->next;current->next = toDel->next;if (next != NULL){next->pre = toDel->pre;}if (m_current == toDel){m_current = toDel->next;}m_length--;destroy(toDel);}return ret;}bool set(int index, const T& e){bool ret = (0 <= index) && (index < m_length);if (ret){position(index)->next->value = e;}return ret;}bool get(int index, T& e) const{bool ret = (0 <= index) && (index < m_length);if (ret){e = position(index)->next->value;}return ret;}virtual T get(int index) const{T ret;if (get(index, ret)){return ret;}else{THROW_EXCEPTION(InvalidParameterException, "Invalid parameter in get element...");}}int find(const T& e) const{int ret = -1;int index = 0;Node* current = m_header.next;while (current){if (current->value == e){ret = index;break;}else{index++;current = current->next;}}return ret;}virtual bool move(int index, int step = 1){bool ret = ((0 <= index) && (index < m_length) && (step > 0));if (ret){m_current = position(index)->next;m_step = step;}return ret;}virtual bool end(){return (m_current == NULL);}virtual T current(){if (!end()){return m_current->value;}else{THROW_EXCEPTION(InvalidOperationException, "Invalid operation to get current value ...");}}virtual bool next(){int i = 0;while ((i < m_step) && (!end())){m_current = m_current->next;i++;}return (i == m_step);}virtual bool pre(){int i = 0;while ((i < m_step) && (!end())){m_current = m_current->pre;i++;}return (i == m_step);}int length() const{return m_length;}void clear(){while (m_length > 0){remove(0);}}~DualLinkList(){clear();} }; }#endif // DUALLINKLIST_Hmain.cpp
#include <iostream>#include "SmartPointer.h" #include "Exception.h" #include "Object.h" #include "List.h" #include "SeqList.h" #include "StaticList.h" #include "DynamicList.h" #include "Array.h" #include "StaticArray.h" #include "DynamicArray.h" #include "LinkList.h" #include "StaticLinkList.h" #include "Pointer.h" #include "SmartPointer.h" #include "SharedPointer.h" #include "CircleList.h" #include "DualLinkList.h"using namespace std; using namespace LemonLib;int main() {DualLinkList<int> dl;for (int i=0; i<5; i++){dl.insert(0, i);dl.insert(0, 8);}int ret = -1;while ((ret = dl.find(8)) != -1){dl.remove(ret);}#if 0 // 這樣刪除的意義不大dl.move(dl.length()-1);while (!dl.end()){if (dl.current() == 8){dl.remove(dl.find(8));}else{dl.pre();}} #endif#if 1for (dl.move(0); !dl.end(); dl.next()){cout << dl.current() << endl;} #endif#if 0for (dl.move(dl.length()-1); !dl.end(); dl.pre()){cout << dl.current() << endl;} #endif#if 0for (int i=0; i<5; i++){cout << dl.get(i) << endl;} #endifreturn 0; }4 開放性問題
DualLinkList和LinkList中存在很多完全一樣的代碼,如何進(jìn)行重構(gòu)降低代碼的冗余性?冗余代碼的出現(xiàn)是否意味著DualLinkList和LinkList之間應(yīng)該是繼承關(guān)系?
解決這個(gè)問題的方法就是DualLinkList繼承LinkList,從而降低代碼的冗余性。關(guān)于DualLinkList是否設(shè)計(jì)為LinkList的子類,這只是設(shè)計(jì)理念不同而已。
總結(jié)
以上是生活随笔為你收集整理的DualLinkList的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。