STL學習筆記之容器 slist

2021-07-03 07:51:31 字數 4737 閱讀 5426

slist是sgi stl裡面的乙個單向鍊錶,不過這個不屬於標準定義,所以,g++下面不能用,另外看了下vs2008裡面也沒有。不過看到書上這一部分講解,還是配合sgi的**做乙個了解。一般情況下使用標準的list就可以滿足要求了,而且會更加方便,list的分析可以參考stl筆記之list一文。因為slist是單向鍊錶,所以它的迭代器型別為forward_iterator。

1. slist節點設計

鍊錶最基本的結構就是指標域和資料域,對單向鍊錶的節點而言,其擁有乙個next指標,指向下乙個節點,同時擁有乙個資料域用於儲存節點的資料。slist在這裡做了乙個分層處理,基類_slist_node_base只有next指標,用於鍊錶的構造,子類_slist_node繼承自_slist_node_base,同時擁有乙個儲存資料的成員。

// node 基類

struct _slist_node_base;

// slist_node

template struct _slist_node : public _slist_node_base

;

一些基本的函式操作,基於_slist_node_base指標型別。可以看到因為單鏈表只能往後迭代,所以很多操作都沒有提供,即使提供了,也是非常低效的操作,需要從頭結點開始遍歷。

// 在prev後面插入新節點,返回指向新的節點的指標

inline _slist_node_base*

__slist_make_link(_slist_node_base* __prev_node,

_slist_node_base* __new_node)

// 返回指定節點的上乙個節點,需要從head開始遍歷

inline _slist_node_base*

__slist_previous(_slist_node_base* __head,

const _slist_node_base* __node)

// 拼接操作:將[before_first->next, before_last]拼接到pos後

inline void __slist_splice_after(_slist_node_base* __pos,

_slist_node_base* __before_first,

_slist_node_base* __before_last)}

// 將head指向的鍊錶拼接到pos之後

inline void

__slist_splice_after(_slist_node_base* __pos, _slist_node_base* __head)}

// 翻轉鍊錶

inline _slist_node_base* __slist_reverse(_slist_node_base* __node)

return __result;}

// 求鍊錶的節點個數

inline size_t __slist_size(_slist_node_base* __node)

2. slist迭代器設計

slist的迭代器屬於forward iterator,只能往前迭代,因此除了迭代器的基本操作之外,只實現了operator++操作。

// iterator基類

struct _slist_iterator_base

// 只提供往前訪問的方法

void _m_incr()

bool operator==(const _slist_iterator_base& __x) const

bool operator!=(const _slist_iterator_base& __x) const };

// 迭代器定義

template struct _slist_iterator : public _slist_iterator_base

_slist_iterator() : _slist_iterator_base(0) {}

_slist_iterator(const iterator& __x) : _slist_iterator_base(__x._m_node) {}

reference operator*() const

pointer operator->() const

_self& operator++()

_self operator++(int)

};

3. slist設計

slist也是分層的設計,_slist_base中定義了乙個型別為_slist_node_base的_m_head成員,head.next即指向鍊錶的第乙個節點。

template struct _slist_base 

// 建構函式,將head.next置為空

_slist_base(const allocator_type&)

// 析構函式, 通過呼叫_m_erase_after刪除所有節點

~_slist_base()

protected:

typedef ******_alloc<_slist_node<_tp>, _alloc> _alloc_type;

_slist_node<_tp>* _m_get_node()

void _m_put_node(_slist_node<_tp>* __p)

// 刪除指定節點後面的節點

_slist_node_base* _m_erase_after(_slist_node_base* __pos)

_slist_node_base* _m_erase_after(_slist_node_base*, _slist_node_base*);

protected:

_slist_node_base _m_head;

};

// 刪除指定節點之後的節點:區間[before_first->next, last)

template _slist_node_base*

_slist_base<_tp,_alloc>::_m_erase_after(_slist_node_base* __before_first,

_slist_node_base* __last_node)

__before_first->_m_next = __last_node;

return __last_node;

}

slist基本結構定義:

template class slist : private _slist_base<_tp,_alloc>

private:

typedef _slist_node<_tp> _node;

typedef _slist_node_base _node_base;

typedef _slist_iterator_base _iterator_base;

_node* _m_create_node(const value_type& __x)

__stl_unwind(this->_m_put_node(__node));

return __node;

} _node* _m_create_node()

__stl_unwind(this->_m_put_node(__node));

return __node;

} public:

iterator begin()

iterator end()

size_type size() const

size_type max_size() const

bool empty() const

void swap(slist& __x)

public:

reference front()

void push_front(const value_type& __x)

void pop_front()

iterator previous(const_iterator __pos)

private:

_node* _m_insert_after(_node_base* __pos, const value_type& __x)

public:

void reverse()

};

4. slist排序

slist的sort**與list的sort**非常類似,可以參考list sort一節。

template void slist<_tp,_alloc>::sort()

__carry.swap(__counter[__i]);

if (__i == __fill)

++__fill;

}for (int __i = 1; __i < __fill; ++__i)

__counter[__i].merge(__counter[__i-1]);

this->swap(__counter[__fill-1]);

}}

至此,stl常見序列容器基本分析完畢,接下來準備看看關聯容器,以及記錄一下使用stl過程中遇到的一些「坑」(比如最近使用sort導致了core dump)。

stl之順序容器學習筆記1

初窺容器 容納特定型別物件的集合,稱為容器。將單一型別的元素聚集起來成為容器,然後根據位置來儲存和訪問元素,稱為順序容器。順序容器的排列次序,按照元素新增到容器的次序決定。stl定義了三種順序容器 1 vector 2 list 3 deque 他們的差異在於訪問元素的方式,以及做新增 刪除元素時的...

stl之順序容器學習筆記3

vector容器的自增長 概述vector物件為了支援快速隨機的訪問,將元素以連續的方式存放 與陣列相同 當我們向vector中新增乙個元素時,如果容器已經沒有空間容納新的元素,此時,由於元素必須連續存放以實現快速索引,所以不能在記憶體中隨便找個地方來儲存這個元素。於是,vector必須重新分配儲存...

stl之關聯容器學習筆記1

概述 stl定義了另一種容器,名曰關聯容器,關聯容器和順序容器的本質區別在於 關聯容器通過鍵key來儲存和讀取元素,而順序容器則通過元素在容器中的位置順序儲存和訪問元素。關聯容器的大部分行為與順序容器相同,但其獨特之處在於支援鍵的使用。stl提供了兩個基本的關聯容器 1 map 容器中以鍵值的形式來...