為了向 STL 致敬(O(∩_∩)O~), 我們模仿STL中的list的迭代器, 我們也自己實現一個MyList的迭代器, 以供遍歷整個鏈表的所有元素:
首先:Node節點需要做如下修改(注意後綴有+的代碼)
//鏈表節點 templateclass Node { friend class MyList ; friend class ListIterator ; //+ template friend ostream &operator<<(ostream &os, const MyList &list); private: Node(const Type &dataValue):data(dataValue), next(NULL) {} Type data; //數據域:節點數據 Node *next; //指針域:下一個節點 };
然後:MyList類同樣也需要做修改,但是由於MyList類過長, 修改之處也較少, 因此在此就不貼出, 完整代碼會附到博客最後
templateclass ListIterator { public: ListIterator(const MyList &_list): list(_list), currentNode((_list.first)->next) {} //重載 *operator const Type &operator*() const throw (std::out_of_range); Type &operator*() throw (std::out_of_range); //重載 ->operator const Node *operator->() const throw (std::out_of_range); Node *operator->() throw (std::out_of_range); //重載 ++operator ListIterator &operator++() throw (std::out_of_range); //注意:此處返回的是值,而不是reference ListIterator operator++(int) throw (std::out_of_range); bool isEmpty() const; private: const MyList &list; Node *currentNode; };
templateconst Type &ListIterator ::operator*() const throw (std::out_of_range) { if (isEmpty()) throw std::out_of_range("iterator is out of range"); // 返回當前指針指向的內容 return currentNode->data; } template Type &ListIterator ::operator*() throw (std::out_of_range) { //首先為*this添加const屬性, //以調用該函數的const版本, //然後再使用const_case, //將該函數調用所帶有的const屬性轉除 //operator->()的non-const版本與此類同 return const_cast ( static_cast &>(*this).operator*() ); }
templateconst Node *ListIterator ::operator->() const throw (std::out_of_range) { if (isEmpty()) throw std::out_of_range("iterator is out of range"); //直接返回指針 return currentNode; } template Node *ListIterator ::operator->() throw (std::out_of_range) { // 見上 return const_cast *> ( static_cast >(*this).operator->() ); }
templateListIterator &ListIterator ::operator++() throw (std::out_of_range) { if (isEmpty()) throw std::out_of_range("iterator is out of range"); //指針後移 currentNode = currentNode->next; return *this; } template ListIterator ListIterator ::operator++(int) throw (std::out_of_range) { ListIterator tmp(*this); ++ (*this); //調用前向++版本 return tmp; }
//判空 templatebool ListIterator ::isEmpty() const { if (currentNode == NULL) return true; return false; }
附-ListIterator測試代碼:
int main() { std::listiStdList; MyList iMyList; for (int i = 0; i < 10; ++i) { iStdList.push_back(i+1); iMyList.insert(i+1, i+1); } for (std::list ::iterator iter = iStdList.begin(); iter != iStdList.end(); ++ iter) { cout << *iter << ' '; } cout << endl; for (ListIterator iter(iMyList); !iter.isEmpty(); ++ iter) { cout << *iter << ' '; } cout << endl; cout << "Test: \n\t" << iMyList << endl; ListIterator iter(iMyList); cout << "first = " << *iter << endl; }
//MyList.h #ifndef MYLIST_H_INCLUDED #define MYLIST_H_INCLUDED #include#include using namespace std; //前向聲明 template class MyList; template class ListIterator; //鏈表節點 template class Node { //可以將MyList類作為Node的友元 //同時也可以將Node類做成MyList的嵌套類, 嵌套在MyList中, 也可以完成該功能 friend class MyList ; friend class ListIterator ; template friend ostream &operator<<(ostream &os, const MyList &list); private: //constructor說明: //next = NULL; //因為這是一個新生成的節點, 因此下一個節點為空 Node(const Type &dataValue):data(dataValue), next(NULL) {} Type data; //數據域:節點數據 Node *next; //指針域:下一個節點 }; //鏈表 template class MyList { template friend ostream &operator<<(ostream &os, const MyList &list); friend class ListIterator ; public: MyList(); ~MyList(); //將元素插入表頭 void insertFront(const Type &data); //將元素插入到位置index上(index從1開始) void insert(const Type &data, int index); //刪除表中所有值為data的節點 void remove(const Type &data); bool isEmpty() const; //鏈表反轉 void invort(); //將鏈表(list)鏈接到本條鏈表的末尾 void concatenate(const MyList &list); private: //指向第一個節點的指針 Node *first; }; template MyList ::MyList() { //first指向一個空節點 first = new Node (0); first -> next = NULL; } template MyList ::~MyList() { Node *deleteNode = NULL; while (first != NULL) { deleteNode = first; first = first -> next; delete deleteNode; } } template void MyList ::insertFront(const Type &data) { Node *newNode = new Node (data); newNode -> next = first -> next; first -> next = newNode; } template void MyList ::insert(const Type &data, int index) { //由於我們在表頭添加了一個空節點 //因此如果鏈表為空, 或者在鏈表為1的位置添加元素 //其操作與在其他位置添加元素相同 int count = 1; //此時searchNode肯定不為NULL Node *searchNode = first; // 找到要插入的位置 // 如果所給index過大(超過了鏈表的長度) // 則將該元素插入到鏈表表尾 // 原因是 searchNode->next != NULL 這個條件已經不滿足了 // 已經到達表尾 while (count < index && searchNode->next != NULL) { ++ count; searchNode = searchNode->next; } // 插入鏈表 Node *newNode = new Node (data); newNode->next = searchNode->next; searchNode->next = newNode; } template void MyList ::remove(const Type &data) { if (isEmpty()) return ; Node *previous = first; //保存要刪除節點的前一個節點 for (Node *searchNode = first->next; searchNode != NULL; searchNode = searchNode->next) { if (searchNode->data == data) { previous->next = searchNode->next; delete searchNode; //重新調整searchNode指針 //繼續遍歷鏈表查看是否還有相等元素 //如果當前searchNode已經到達了最後一個節點 //也就是searchNode->next已經等於NULL了, 則下面這條語句不能執行 if (previous->next == NULL) break; searchNode = previous->next; } previous = searchNode; } } template bool MyList ::isEmpty() const { return first->next == NULL; } template void MyList ::concatenate(const MyList &list) { if (isEmpty())//如果自己的鏈表為空 { first = list.first; return ; } else if (list.isEmpty()) //如果第二條鏈表為空 { return ; } Node *endNode = first->next; //找到第一條鏈表的末尾節點 while (endNode->next != NULL) { endNode = endNode->next; } //找到第二條鏈表的第一個真實元素 Node *secondListNode = (list.first)->next; //注意: 需要將第二個鏈表中的元素值copy出來 //不能直接將第二條鏈表的表頭鏈接到第一條鏈表的表尾 //不然在析構函數回收內存時會發生錯誤(即:同一段內存釋放兩次) while (secondListNode != NULL) { Node *newNode = new Node (secondListNode->data); newNode->next = NULL; endNode->next = newNode; //兩條鏈表同時前進 endNode = endNode->next; secondListNode = secondListNode->next; } } template void MyList ::invort() { if (!isEmpty()) { //p指向正向鏈表的第一個真實節點 //隨後, p也會沿正方向遍歷到鏈表末尾 Node *p = first->next; //q會成為倒向的第一個真實節點 //首先將q設置為NULL: 保證反向之後 //最後一個元素的指針域指向NULL, 以表示鏈表結束 Node *q = NULL; while (p != NULL) { Node *r = q; //暫存q當前指向的節點 //q後退(沿著正向後退) q = p; //p前進(沿著正向前進), 保證p能夠始終領先q一個位置 p = p -> next; //將指針逆向反轉 //注意:一點要保證這條語句在p指針移動之後運行, //不然p就走不了了...(因為q改變了指針的朝向) q -> next = r; } //此時q成為反向鏈表的第一個真實元素 //但是為了維護像以前一樣的first指針指向一個無用的節點(以使前面的操作不會出錯) //於是我們需要將first的指針域指向q first->next = q; } } //顯示鏈表中的所有數據(測試用) template ostream &operator<<(ostream &os, const MyList &list) { for (Node *searchNode = list.first -> next; searchNode != NULL; searchNode = searchNode -> next) { os << searchNode -> data; if (searchNode -> next != NULL) //尚未達到鏈表的結尾 cout << " -> "; } return os; } //ListIterator的設計與實現 template class ListIterator { public: ListIterator(const MyList &_list): list(_list), currentNode((_list.first)->next) {} //重載 *operator const Type &operator*() const throw (std::out_of_range); Type &operator*() throw (std::out_of_range); //重載 ->operator const Node *operator->() const throw (std::out_of_range); Node *operator->() throw (std::out_of_range); //重載 ++operator ListIterator &operator++() throw (std::out_of_range); //注意:此處返回的是值,而不是reference ListIterator operator++(int) throw (std::out_of_range); bool isEmpty() const; private: const MyList &list; Node *currentNode; }; template const Type &ListIterator ::operator*() const throw (std::out_of_range) { if (isEmpty()) throw std::out_of_range("iterator is out of range"); // 返回當前指針指向的內容 return currentNode->data; } template Type &ListIterator ::operator*() throw (std::out_of_range) { //首先為*this添加const屬性, //以調用該函數的const版本, //然後再使用const_case, //將該函數調用所帶有的const屬性轉除 //operator->()的non-const版本與此類同 return const_cast ( static_cast &>(*this).operator*() ); } template const Node *ListIterator ::operator->() const throw (std::out_of_range) { if (isEmpty()) throw std::out_of_range("iterator is out of range"); //直接返回指針 return currentNode; } template Node *ListIterator ::operator->() throw (std::out_of_range) { // 見上 return const_cast *> ( static_cast >(*this).operator->() ); } template ListIterator &ListIterator ::operator++() throw (std::out_of_range) { if (isEmpty()) throw std::out_of_range("iterator is out of range"); //指針前移 currentNode = currentNode->next; return *this; } template ListIterator ListIterator ::operator++(int) throw (std::out_of_range) { ListIterator tmp(*this); ++ (*this); //調用前向++版本 return tmp; } template bool ListIterator ::isEmpty() const { if (currentNode == NULL) return true; return false; } #endif // MYLIST_H_INCLUDED