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

猜你喜欢

转载自blog.csdn.net/qq_38790716/article/details/84553488