STL笔记之slist

slist:单向链表(single linked list)

slist与双向链表的主要差别在于,前者的迭代器属于forward iterator,后者的迭代器属于bidirectional iterator。单向链表所耗用空间更小,某些操作更快,但一些功能受到限制。

根据STL的习惯,插入操作会将新元素插入于指定位置之前,而作为一个单向链表,slist没有任何方便的办法可以回头定出前一个位置,因此它必须从头找起。也就是说,除了slist起点处附近的区域外,在其它位置采用insert或erase操作函数,都属于不智之举。这就是slist相较于list之下的大缺点。为此slist提供了insert_after()和erase_after()。

基于效率考虑,slist不提供push_back(),只提供push_front()。因此slist的元素次序和元素插入的次序相反。

节点

//单向链表的节点基本结构
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* new_node)
{
	//令new节点的下一节点为prev节点的下一节点
	new_node->next = prev_node->next;
	prev_node->next = new_node;//令prev节点的下一节点指向new节点
	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;
}

迭代器

//单向链表的迭代器基本结构
struct __slist_iterator_base
{
	typedef size_t size_type;
	typedef ptrdiff_t difference_type;
	typedef forward_iterator_tag iterator_category;

	__slist_node_base* node;//指向节点基本结构
	__slist_iterator_base(__slist_node_base* x):node(x){}
	
	void incr() { node = node->next; }

	bool operator==(const __slist_iterator_base& x)const {
		return node == x.node;
	}
	bool operator!=(const __slist_iterator_base& x)const {
		return node != x.node;
	}
};

//单向链表的迭代器结构
template<class T,class Ref,class Ptr>
struct __slist_iterator:pulic __slist_iterator_base
{
	typedef __slist_iterator<T, T&, T*> iterator;
	typedef __slist_iterator<T, const T&, const T*> const_iterator;
	typedef __slist_iterator<T, Ref, Ptr> self;

	typedef T value_type;
	typedef Ptr pointer;
	typedef Ref reference;
	typedef __slist_node<T> list_node;

	__slist_iterator(list_node* x):__slist_iterator_base(x){}
	//调用slist<T>::end()时会造成__slist_iterator(0),于是调用上述函数
	__slist_iterator() :__slist_iterator_base(0) {}
	__slist_iterator(const iterator& x):__slist_iterator_base(x){}

	reference operator*()const { return ((list_node*)node)->data; }
	pointer operator->()const { return &(operator*()); }

	self& operator++() {
		incr();
		return *this;
	}
	self operator++(int) {
		self tmp = *this;
		incr();
		return tmp;
	}
	//因为是一个forward iterator所以没有operator--
};

比较两个slist迭代器是否等同时,由于__slist_iterator并未对operator==进行重载,所以会调用__slist_iterator_base::operator==,故两个slist迭代器是否等同,看其__slist_node_base* node是否等同而定。

数据结构

template<class T,class Alloc=alloc>
class slist
{
public:
	typedef T value_type;
	typedef value_type* pointer;
	typedef const value_type* const_pointer;
	typedef size_t size_type;
	typedef ptrdiff_t difference_type;

	typedef __slist_iterator<T, T&, T*> iterator;
	typedef __slist_iterator<T, const T&, const T*> const_iterator;

private:
	typedef __slist_node<T> list_node;
	typedef __slist_node_base<T> llist_node_base;
	typedef __slist_iterator_base iterator_base;
	typedef simple_alloc<list_node, Alloc> list_node_allocator;

	static list_node* create_node(const value_type& x) {
		list_node* node = list_node_allocator::allocate();
		__STL_TRY{
			construct(&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(); }

public:
	iterator begin() { return iterator((list_node*)head.next); }
	iterator end() { return itertor(0); }
	size_type size()const { return __slist_size(head.next); }
	bool empty()const { return head.next == 0; }

	//两个slist互换,只需要将head交换互指即可
	void swap(slist& L)
	{
		list_node_base* tmp = head.next;
		head.next = L.head.next;
		L.head.next = tmp;
	}

public:
	//取头部元素
	reference front() { return ((list_node*)head.next)->data; }

	//从头部插入元素(新元素成为slist的第一个元素
	void push_front(const value_type& x)
	{
		__slist_make_link(&head, create_node(x));
	}
	//没有push_back()
	
	//从头部取走元素(删除之),修改head
	void pop_front() {
		list_node* node = (list_node*)head.next;
		head.next = node->next;
		destroy_node(node);
	}
//...
};



猜你喜欢

转载自blog.csdn.net/s_hit/article/details/79520395