4 序列式容器(续)——container adapter

4.5 stack

template <class T, class Sequence = deque<T> >
class stack {
	// 以下的__STL_NULL_TMPL_ARGS 會開展為<>,見1.9.1 節
	friend bool operator==__STL_NULL_TMPL_ARGS (const stack&, const stack&);
	friend bool operator<__STL_NULL_TMPL_ARGS (const stack&, const stack&);
public:
	typedef typename Sequence::value_type value_type;
	typedef typename Sequence::size_type size_type;
	typedef typename Sequence::reference reference;
	typedef typename Sequence::const_reference const_reference;
protected:
	Sequence c; // 底層容器
public:
	// 以下完全利用Sequence c 的操作,完成stack 的操作。
	bool empty() const { return c.empty(); }
	size_type size() const { return c.size(); }
	reference top() { return c.back(); }
	const_reference top() const { return c.back(); }
	// deque 是兩頭可進出,stack 是末端進,末端出(所以後進者先出)。
	void push(const value_type& x) { c.push_back(x); }
	void pop() { c.pop_back(); }
};
template <class T, class Sequence>
bool operator==(const stack<T, Sequence>& x, const stack<T, Sequence>& y)
{
	return x.c == y.c;
}
template <class T, class Sequence>
bool operator<(const stack<T, Sequence>& x, const stack<T, Sequence>& y)
{
	return x.c < y.c;
}

注意:stack没有迭代器

 

4.6 queue

template <class T, class Sequence = deque<T> >
class queue{
	// 以㆘的__STL_NULL_TMPL_ARGS 會開展為<>,見1.9.1 節
	friend bool operator== __STL_NULL_TMPL_ARGS (const queue& x, const queue& y);
	friend bool operator< __STL_NULL_TMPL_ARGS (const queue& x, const queue& y);
public:
	typedef typename Sequence::value_type value_type;
	typedef typename Sequence::size_type size_type;
	typedef typename Sequence::reference reference;
	typedef typename Sequence::const_reference const_reference;
protected:
	Sequence c; // 底層容器
public:
	// 以下完全利用Sequence c 的操作,完成queue 的操作。
	bool empty() const { return c.empty(); }
	size_type size() const { return c.size(); }
	reference front() { return c.front(); }
	const_reference front() const { return c.front(); }
	reference back() { return c.back(); }
	const_reference back() const { return c.back(); }
	// deque 是兩頭可進出,queue 是末端進,前端出(所以先進者先出)。
	void push(const value_type& x) { c.push_back(x); }
	void pop() { c.pop_front(); }
};
template <class T, class Sequence>
bool operator==(const queue<T, Sequence>& x, const queue<T, Sequence>& y)
{
	return x.c == y.c;
}
template <class T, class Sequence>
bool operator<(const queue<T, Sequence>& x, const queue<T, Sequence>& y)
{
	return x.c < y.c;
}

注意:queue没有迭代器


4.7 heap

heap并不属于STL容器组件,而是用于priority queue。heap内部用vector实现。

1、push_heap,pop_heap,sort_heap(将heap排序成由小到大),make_heap(默认生成最大堆)

注意:push_heap调用前程序员自行将元素push_back到vector中;pop_heap之后元素只是放置于尾部,并未取走,程序员自行调用pop_back取走。

2、heap没有迭代器


4.8 priority_queue

以vector为底部容器,再加上heap处理规则;默认为最大堆,默认大小比较规则为less;无迭代器

template <class T, class Sequence = vector<T>,
class Compare = less<typename Sequence::value_type> >
class priority_queue{
public:
	typedef typename Sequence::value_type value_type;
	typedef typename Sequence::size_type size_type;
	typedef typename Sequence::reference reference;
	typedef typename Sequence::const_reference const_reference;
protected:
	Sequence c; // 底層容器
	Compare comp; // 元素大小比較標準
public:
	priority_queue() : c() {}
	explicit priority_queue(const Compare& x) : c(), comp(x) {}
	// 以下用到的make_heap(), push_heap(), pop_heap()都是泛型演算法
	// 注意,任一個构造函数都立刻於底层容器內產生一個implicit representation heap。
	template <class InputIterator>
	priority_queue(InputIterator first, InputIterator last, const Compare& x)
		: c(first, last), comp(x) { make_heap(c.begin(), c.end(), comp); }
	template <class InputIterator>
	priority_queue(InputIterator first, InputIterator last)
		: c(first, last) { make_heap(c.begin(), c.end(), comp); }
	bool empty() const { return c.empty(); }
	size_type size() const { return c.size(); }
	const_reference top() const { return c.front(); }
	void push(const value_type& x) {
		__STL_TRY {
			// push_heap 是泛型演算法,先利用底層容器的push_back() 將新元素
			// 推入末端,再重排heap。見C++ Primer p.1195。
			c.push_back(x);
			push_heap(c.begin(), c.end(), comp); // push_heap 是泛型演算法
		}
		__STL_UNWIND(c.clear());
	}
	void pop() {
		__STL_TRY {
			// pop_heap 是泛型演算法,從heap 內取出㆒個元素。它並不是真正將元素
			// 彈出,而是重排heap,然後再以底層容器的pop_back() 取得被彈出
			// 的元素。見C++ Primer p.1195。
			pop_heap(c.begin(), c.end(), comp);
			c.pop_back();
		}
		__STL_UNWIND(c.clear());
	}
};


4.9 slist

SGI STL提供了一个单向链表slist(不属于标准规格,STL list是个双向链表)。slist的迭代器属于单向的Forward Iterator。注意,由于一个单向链表不能回头定出前一个位置,必须从头找起,所以只提供push_front(),而不提供push_back(),也不应该调用insert(插入操作会将新元素插入到指定位置之前,而非之后)或erase成员函数,不过slist还提供了insert_after()和erase_after()函数。


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


2、slist的迭代器

// 單向串列的迭代器基本結構
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: public __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(constiterator& x) : __slist_iterator_base(x.node) {}
	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;
	}
	// 沒有實作operator--,因為這是㆒個forward iterator
};



3、slist的实现

template <class T, class Alloc = alloc>
class slist
{
public:
	typedef T value_type;
	typedef value_type* pointer;
	typedef const value_type* const_pointer;
	typedef value_type& reference;
	typedef const value_type& const_reference;
	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 list_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 iterator(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);
	}
	...
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值