1. 程式人生 > >STL原始碼剖析(四)序列式容器--slist

STL原始碼剖析(四)序列式容器--slist

文章目錄

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;
}