資料結構 筆記:雙向連結串列的實現
阿新 • • 發佈:2018-12-16
單鏈表的另一個缺陷
-單向性
·只能從頭結點開始高效訪問連結串列中的資料元素
-缺陷
·如果需要逆向訪問單鏈表中的資料元素將極其低效
雙向的線性表
-在“單鏈表”的結點中增加一個指標pre,用於指向當前結點的前驅結點
雙向連結串列的繼承層次結構
DualLinkList的定義
template<typename T> class DualLinkList : public List<T> { protected: struct Node :public Object { T value; Node* next; Node* pre; }; mutable // struct{ // char reserved[sizeof(T)]; // Node* next; // } Node m_header; Node* position(int i) const { Node* ret = reinterpret_cast<Node*>(&m_header); for(int p=0;p<i;p++) { ret = ret->next; } return ret; } virtual Node* create() { return new Node(); } virtual void destroy(Node* pn) { delete pn; } int m_step; Node* m_current; int m_length; public: DualLinkList() { //m_header.reserved("nul"); m_header.next = NULL; m_header.pre = NULL; m_step = 1; m_current = NULL; m_length = 0; } virtual bool insert(const T& e) { return insert(m_length,e); } virtual bool insert(int i,const T& e) { bool ret = ((0 <= i) && (i <= m_length)); if(ret) { Node* node = create(); if( node != NULL) { Node *current = position(i); Node* next = current->next; //Node* pre = current->pre; //qDebug() << current; node->value = e; node->next = current->next; current->next = node; //qDebug() << "i = " << i <<" , e = " << e << " " << m_length; if(current != reinterpret_cast<Node*>(&m_header)) { //qDebug() << 1; node->pre = current; next->pre = NULL; } else { //qDebug() << 2; node->pre = NULL; } if(next != NULL) { //qDebug() << 4; next->pre = node; } //qDebug() << 5; m_length++; } else { //丟擲異常 //qDebug() << "錯錯了"; } } return ret; } virtual bool remove(int i) { bool ret = ((0 <= i) && (i < m_length)); if(ret) { Node* current = position(i); Node* toDel = current->next; Node* next = toDel->next; if(m_current == toDel) { m_current = next; } current->next = next; if(next != NULL) { next->pre = toDel->pre; } m_length--; destroy(toDel); } return ret; } virtual bool set(int i,const T& e) { bool ret = ((0 <=i ) && (i < m_length)); if(ret) { Node* current = position(i); current->next->value = e; } return ret; } virtual T get(int i) const { T ret; if(get(i,ret)) { return ret; } else { //丟擲異常 //qDebug() << "錯了"; } } virtual bool get(int i, T& e) const { bool ret = ((0 <=i ) && (i < m_length)); if(ret) { Node* current = position(i); e = current->next->value; //qDebug() << e; } return ret; } virtual int length() const { return m_length; } int find (const T& e) const { int ret = -1; int i = 0; Node* node = m_header.next; while(node) { if(node->value == e) { ret = i; break; } else { node = node->next; i++; } } return ret; } virtual void clear() { while(m_length > 0) { remove(0); } m_length = 0; } virtual bool move(int i,int step = 1) { bool ret = (0 <= i)&& (i< m_length) && (step >0); if(ret) { m_current = position(i)->next; m_step = step; } return ret; } virtual bool end() { return (m_current == NULL); } virtual T current() { if(!end()) { return m_current->value; } else { //丟擲異常 } } 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); } ~DualLinkList() { clear(); } };
總結:
-雙向連結串列是為了彌補單鏈表的缺陷而重新設計的
-再概念上,雙向連結串列不是單鏈表,沒有繼承關係
-雙向連結串列中的遊標能夠直接訪問當前結點的前驅和後繼
-雙向連結串列是線性表概念的最終實現(更貼近理論上的線性表)