stl源码剖析 详细学习笔记priority_queue slist
//
// priority_queue.cpp
// 笔记
//
// Created by fam on 15/3/16.
//
//
//---------------------------15/03/16----------------------------
//priority_queue
{
/*
priority_queue概述:
同正常队列一样,队尾进,队首出,不过不是先进后出,
有权值的概念,所以会自动排序(并不是全部排序,只要保证队
首值最大即可,权值最高的最先出队列,这里用的是堆来保证队首
的值
*/
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(){};
//explict
可以有效防止隐式转化
explicit priority_queue(const Compare& x) : c(), comp(x){}
//下面都是直接调用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
{
c.push_back(x);
push_heap(c.begin(), c.end(), comp);
}
__STL_UNWIND(c.clear());
}
void pop()
{
__STL_TRY
{
pop_heap(c.begin(), c.end(), comp);
c.pop_back();
}
__STL_UNWIND(c.clear());
}
/*
总结:
同queue
不提供迭代器。
不同queue,底层实现是用vector实现的(queue底层是deque实现的)
原因:queue每次进队列都在队尾,出队列都在队首,频繁地对头尾进行操作,
deque比vector性能好很多
priority_queue虽然也是队尾进,队首出,但是不可避免的是每次都要调整位置,
所以采用堆加vector是很好的选择(deque的随机访问是要比vector慢的),采用
堆每次插入,取出,都只用log(n)的时间,所以很好.
*/
};
}
//slist
{
/*
slist概述:
list是双向链表(double linked list),slist是单向链表
slist的迭代器属于单向的ForwardIterator,所以功能被限制了很多
但是耗用的空间小,操作更快.(我们大部分人最先接触的链表数据结构就是单向链表)
slist不提供push_back(),
*/
//__slist_node
struct __slist_node_base
{
__slist_node_base* next;
};
template <class T>
struct __slist_node :
public __slist_node_base
{
T data;
};
//添加一个节点(new_node)到prev_node之后
inline __slist_node_base* __slist_make_link(
__slist_node_base* prev_node,
__slist_node_base* new_node)
{
new_node->next = prev_node->next;
prev_node->next = new_node;
return new_node;
}
//通过循环判断node节点之后(包括node节点)一共有多少节点
inline size_t __slist_size(__slist_node_base* node)
{
size_t result =
;
; node = node->next)
++result;
return result;
}
//__slist_iterator
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;
}
};
//T: class Ref class& Ptr class*
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_iterator() : __slist_iterator_base(){}
__slist_iterator(const iterator& x) : __slist_iterator_base(x.node) {}
//node是__slist_node_base类型
需要强制转化
reference
operator*() const {return ((list_node*) node)->data;}
pointer
operator->() const {return &(operator*());}
self&
operator++()
{
incr();
return *this;
}
self
operator++(int)
{
self temp = *this;
incr();
return temp;
}
//并没有operator--操作
};
//class slist
template< class T,
class Alloc = allic>
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=;
}
__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 =
; }
//clear()是循环删除所有节点
~slist() {clear();}
iterator begin() {return iterator((list_node*)head.next);}
//强制转化一个0为iterator类型表示end
//最开始的时候,head.next等于0
表示末尾;
iterator end() {);}
size_type size()
const {return __slist_size(head.next);}
bool empty() const {return head.next ==
;}
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;}
void push_front(const value_type& x)
{
__slist_make_link(&head, create_node(x));
}
void pop_front()
{
list_node* node = (list_node*) head.next;
head.next = node->next;
destroy_node(node);
}
};
/*
总结:
同deque一样,我还是不知道为什么在迭代器中会有self和iterator两个typedef
为什么要特地弄出两个基类?
这样的好处貌似是一个链表可以存放不同的数据类型,但是
并没有用啊。在使用slist<T>来声明定义变量时就确定了类型了。
别的没什么特别的技巧,就是一个很普通的list
*/
}
stl源码剖析 详细学习笔记priority_queue slist的更多相关文章
- stl源码剖析 详细学习笔记 hashtable
//---------------------------15/03/24---------------------------- //hashtable { /* 概述: sgi采用的是开链法完成h ...
- stl源码剖析 详细学习笔记 set map
// // set map.cpp // 笔记 // // Created by fam on 15/3/23. // // //---------------------------15/03 ...
- stl源码剖析 详细学习笔记 RB_tree (1)
// // RB_tree_STL.cpp // 笔记 // // Created by fam on 15/3/21. // // #include "RB_tree_STL.h&q ...
- stl源码剖析 详细学习笔记heap
// // heap.cpp // 笔记 // // Created by fam on 15/3/15. // // //---------------------------15/03/15 ...
- stl源码剖析 详细学习笔记 空间配置器
//---------------------------15/04/05---------------------------- /* 空间配置器概述: 1:new操作包含两个阶段操作 1>调 ...
- stl源码剖析 详细学习笔记 算法(1)
//---------------------------15/03/27---------------------------- //算法 { /* 质变算法:会改变操作对象之值 所有的stl算法都 ...
- stl源码剖析 详细学习笔记 算法总览
//****************************基本算法***************************** /* stl算法总览,不在stl标准规格的sgi专属算法,都以 *加以标 ...
- stl源码剖析 详细学习笔记 RB_tree (2)
//---------------------------15/03/22---------------------------- //一直好奇KeyOfValue是什么,查了下就是一个和仿函数差不多 ...
- stl源码剖析 详细学习笔记stack queue
// // stack.cpp // 笔记 // // Created by fam on 15/3/15. // // //---------------------------15/03/1 ...
随机推荐
- Mbps Mb M Kb如何换算
在传输单位的写法上,B 和 b 分别代表 Bytes 和 bits,两者的定义是不同的,具体换算公式如下:1 Byte = 8 bits 1 Kb = 1024 bits 1 KB = 1024 by ...
- 转:asp.net mvc下的多语言方案 包含Html,Javascript和图片
可以不使用微软的Resource文件,而是将所有的词汇放入在一个txt的词典之中,便于维护. 步骤如下: 1)在整个程序的入口处global.asax.cs加入函数 private void Read ...
- crm lookup
1. 大家都知道CRM 里面的Lookup 保存了相关实体的GUID,让我们深入的了解一下CRM Lookup.当我们在2个实体间建立关系的时候,CRM自动生成了一些attributes来保存相关实体 ...
- Node.js环境搭建和学习(windwos环境)
Node.js环境搭建和学习 一.环境搭建 1.下载安装文件 下载地址http://nodejs-org.qiniudn.com/下载Node.js环境安装包,根据操作系统下载对应的安装包 下载地址 ...
- route命令详解与使用实例 ,同时访问内外网
route命令详解与使用实例 2011-10-18 12:19:41| 分类: 其他 | 标签:route |字号 订阅 1. 使用背景 需要接入两个网络,一个是部署环境所在内 ...
- PAT乙级真题及训练题 1025. 反转链表 (25)
PAT乙级真题及训练题 1025. 反转链表 (25) 感觉几个世纪没打代码了,真是坏习惯,调了两小时把反转链表调出来了,心情舒畅. 这道题的步骤 数据输入,数组纪录下一结点及储存值 创建链表并储存上 ...
- 服务器上u盘装机centos7.2
说明: 截止目前CentOS 7.x最新版本为CentOS 7.2.1511,下面介绍CentOS 7.2.1511的具体安装配置过程 服务器相关设置如下: 操作系统:CentOS 7.2.1511 ...
- linux 删除指定日期之前的文件
两种方法: 1. 在一个目录中保留最近三个月的文件,三个月前的文件自动删除. find /email/v2_bak -mtime +92 -type f -name *.mail[12] -exec ...
- 谁对EXTJS熟悉,有关关闭panel的问题?
谁对EXTJS熟悉,有关关闭panel的问题?比如:我在A.js 中写了一个 var win = new Ext.Window( { b.js }); win.show(); 打开了一 ...
- Sql注入测试--Sqlmap
慕课网sqlmap学习笔记: 一.SQL注入 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令. 例如 (1)在url上 ...