STL原始碼剖析(四)序列式容器--slist
阿新 • • 發佈:2018-12-03
文章目錄
1. slist概述
slist,即我們資料結構課程中所學的單鏈表,與之非常類似的是我們前面所解析到的list
- slist與list的主要差別在於:slist的迭代器屬於單向的Forward iterator,list的迭代器則屬於Bidirectional iterator;因此slist的功能受到限制,不過其耗用空間比較少,某些操作快
- 作為一個單向連結串列,其侷限性在於插入的時候需要將元素插入到指定位置之前,然後沒有辦法回頭定出前一個位置,因此除了在slist頭尾及附近的位置之外,在其它位置上不採用insert或erase操作
2. slist的節點及迭代器
- slist節點及迭代器在設計上比list更為複雜,使用了繼承關係,即節點繼承自__slist_node_base,迭代器繼承自__slist_iterator_base,這種設計方式被稱為
雙層設計
,在後續的RB-tree設計中也能再次看到
2.1節點設計:
//單向連結串列的節點基本結構
struct __slist_node_base {
__slist_node_base* next;
};
//單向連結串列的節點結構
template <class T>
struct __slist_node : public __slist_node_base {
T data;
};
//全域性函式:插入新節點於,某個已知節點之後
inline __slist_node_base * __slist_make_link (
__slist_node_base* prev_node,
__slist_node_base* next_node)
{
new_node->next = prev_node->next;
prev_node->next = new_node;
return new_node;
}
//全域性函式:單鏈表的大小
inline size_t __slist_size(__slist_node_base* node)
{
size_t result = 0;
for (; node != 0; node = node->next)
++result;
return result;
}
2.2 迭代器設計:
//單鏈表迭代器基本結構
struct __slist_iterator_base {
//...迭代器型別定義
__slist_node_base* node; //指向節點的基本結構
__slist_iterator_base (__slist_node_base* x) : node(x) {}
void incr() { node = node->next; } //前進一個節點
bool operator== (const __slist_node_base& x) const {
return node == x.node;
}
bool operator!=(const __slist_node_base& x) const {
return node != x.node;
}
};
//單鏈表迭代器結構
struct __slist_iterator : public __slist_iterator_base {
//...迭代器型別與型別定義
//...各類建構函式定義
reference oeprator*() const { return ((list_node*) node) -> data; } //取值操作符過載
reference operator->() const { return &(oeprator*()); }
//過載++運算子
self& operator++()
{
incr();
return *this;
}
self operator++(int)
{
self tmp = *this;
incr();
return tmp;
}
};
3. 資料結構
- slist的基本實現,建立節點、釋放節點以及對元素的一些基本操作,部分原始碼如下:
template <class T, class Alloc = alloc>
class slist {
public:
//節點及迭代器的定義
private:
//...
static list_ndoe* create_node(const value_type& x) {
list_node* node = list_node_allocator::allocate();
__STL_TRY {
construcr(&node->data,x); //構造元素
node->next = 0;
}
__STL_UNWIND(list_node_allocator::deallocate(node);
return node;
}
static void destroy_node (list_node* node ) {
destroy(&node->data;}
list_node_allocator::deallocate(node); //將元素析構
}
private:
list_node_base head;
public:
slist() { head.next = 0;}
~slist() { clear();}
void swap (slist& l) { //交換兩個單鏈表,只需將head交換
list_node_base* tmp = head.next;
head.next = l.head.next;
l.head.next = tmp;
}
//...一些元素操作
};
4. 元素操作
操作 | 功能 |
---|---|
front | 取頭部元素 |
push_front | 從頭部插入元素 |
pop_front | 從頭部取走元素 |
- 例項:
#include <iostream>
#include <slist>
using namespace std;
int main(int argc, char** argv) {
slist<int> sli;
cout << " size = " << sli.size() << endl; //size = 0
sli.push_front(9);
sli.push_front(1);
sli.push_front(2);
sli.push_front(3);
sli.push_front(4);
cout << " size = " << sli.size() << endl; //size = 5
slist<int>::iterator it1 = sli.begin();
slist<int>::iterator it2 = sli.end();
for (; it1 != it2 ; ++it1)
cout << *it1 << ' '; //4 3 2 1 9
cout << endl;
cout << sli.front(); //4
return 0;
}