單向鏈表-slist
博主所分享的這個單向鏈表slist,是依據侯捷老師的《STL源碼解析》中slist一節的slist,因爲博主在跑書上slist上的例子時,發現#include
節點的定義
節點的定義如下,定義在nodeStruct.h的頭文件中:
//nodeStruct.h
template<class T>
struct nodeStruct{
T data;
nodeStruct* next;
};
slist迭代器的定義
迭代器的定義如下,定義在slist_iterator.h的頭文件中:
//slist_iterator.h
#include "nodeStruct.h"
template<class T,class Ref,class Ptr>
class iterator_{
typedef iterator_<T, T&, T*> iterator;
typedef iterator_<T, const T&, const T*> const_iterator;
typedef iterator_<T, Ref, Ptr> self;
typedef T value_type;
typedef Ref reference;
typedef Ptr pointer;
typedef nodeStruct<T> node;
public:
node* nnn;//定義一個node節點
public:
iterator_(node* x) :nnn(x){}//構造函數
iterator_() : nnn(0){}//構造函數
iterator_(const iterator& iter) :nnn(iter.nnn){}//拷貝構造函數
//重載等號運算符
self& operator=(const iterator& iter)
{
nnn = iter.nnn;
return *this;
}
//判斷兩個迭代器是否相等
bool operator==(const iterator& iter)
{
return nnn == iter.nnn;
}
//判斷兩個迭代器是否不相等
bool operator!=(const iterator& iter)
{
return nnn != iter.nnn;
}
//迭代器自增
self& operator++()
{
nnn = nnn->next;
return *this;
}
//迭代器自增
self operator++(int)
{
self tmp = *this;
++(*this);
return tmp;
}
//重載+=運算符
self operator+=(int n)
{
while (n-- > 0)
{
if (nnn == 0)
return iterator(0);
nnn = nnn->next
}
return *this;
}
//重載*運算符,獲取數據
reference operator*()
{
return nnn->data;
}
//重載->運算符,獲取數據的地址
pointer operator->()
{
return &(operator*());
}
};
slist數據結構的定義
數據結構的定義如下,定義在slist.h的頭文件中:
//slist.h
#include "slist_iterator.h"
template<class T>
class slist{
typedef T value_type;
typedef value_type& reference;
typedef const reference const_reference;
typedef value_type* pointer;
typedef const pointer const_pointer;
typedef nodeStruct<T> node;
private:
node* head;//設置一個頭結點
public:
typedef iterator_<T, T&, T*> iterator;
typedef iterator_<T, const T&, const T*> const_iterator;
//構造函數初始化,將頭結點head的數據域data設置爲0,指針域next設置爲0
//頭指針不存儲任何有用的數據,僅僅是爲了方便數據的運算操作而出現的
slist(){
head = new node();
head->data = 0;
head->next = 0;
}
//析構函數,使用完slist後,釋放每個節點的內存
~slist(){
node* tmp = head->next;
while (tmp != 0)
{
node* next = tmp->next;
delete tmp;
tmp = next;
}
}
//向鏈表slist中插入節點,新節點一般插入到頭結點head的後面,所以節點的插入
//的順序與它在鏈表中的順序是相反的
void push_front(reference val)
{
//node* pn = (node*)(malloc(sizeof(node)));
node* pn = new node();
pn->data = val;
pn->next = head->next;
head->next = pn;
}
//將頭節點之後的第一個節點清除掉
void pop_front()
{
if (head->next != 0)
{
node* pn = head->next;
head->next = pn->next;
delete pn;
}
}
//獲取slist中節點的個數,不包含頭結點
size_t size() const
{
size_t size=0;
if (head->next == 0)
{
return 0;
}
node* tmp = head->next;
while (tmp != 0)
{
size++;
tmp = tmp->next;
}
return size;
}
//交換兩個slist
void swap(slist& L)
{
node* tmp = head->next;
L.head->next = tmp;
head->next = L.head->next;
}
//判斷目前slist是否含有節點,不包含頭結點
bool empty()const
{
return head->next == 0;
}
//從頭結點後的第一個節點開始,依次展示slist中存儲的所有數據
void showList()const
{
node* tmp = head->next;
while (tmp != 0)
{
cout << tmp->data << ' ';
tmp = tmp->next;
}
cout << endl;
}
//獲取slist開始的迭代器
iterator begin()
{
return iterator(head->next);
}
//獲取slist結束的迭代器
iterator end()
{
return iterator(0);
}
//向slist中的某個位置之前插入節點,通過迭代器來完成
iterator insert(iterator& iter, value_type val)
{
iterator beg = begin();
while(beg != end())
{
iterator next = beg;
++next;
if (next == iter)
{
node* tmp = new node();
tmp->data = val;
tmp->next = (beg.nnn)->next;
(beg.nnn)->next = tmp;
return iterator(tmp);返回當前插入位置的迭代器
}
beg = next;
}
return beg;//如果沒有找到要插入的位置,返回最後一個節點所表示的迭代器
}
//將slist中某個位置的節點刪除,通過迭代器來完成,返回所刪除節點指向的下一
//個節點所表示的迭代器
iterator erase(iterator& iter)
{
iterator beg = begin();
while (beg != end())
{
iterator next = beg;
++next;
if (next == iter)
{
(beg.nnn)->next = (iter.nnn)->next;
delete iter.nnn;
return ++beg;
}
beg = next;
}
return beg;
}
};
至此,簡單的slist的已經完成,下面我們來做一小下測試:
//slistTest.h
#include "slist.h"
using namespace std;
int main(){
slist<int> li;
for (int i = 0; i < 10; i++)
li.push_front(i);
cout << "The initial sequence of integers is : ";
li.showList();
slist<int>::iterator beg = li.begin();
beg += 4;//從首位置向後移四位
slist<int>::iterator it=li.insert(beg,100);//插入100,返回插入節點所在位置的迭代器
cout <<"The insert number is : "<< *it << endl;
cout << "After insert the integer 100, the sequence of integers is :";
li.showList();
slist<int>::iterator cur = li.erase(beg);
//cout << *cur << endl;
cout << "After erase the iterator beg, the sequence of integers is :";
li.showList();
system("pause");
}
測試結果如下:
測試的結果是正確的!
通過實現slist的簡單實現,讓自己對迭代器有了深入的理解,其實說的明白一點迭代器就是一個被封裝的節點指針,通過給它賦值,自增等運算後可以指向任何位置的節點。廢話不多說了,《STL源碼解析》裏自己還有很多東西需要啃,加油!