您的位置:首页 > 产品设计 > UI/UE

stl源码剖析 详细学习笔记priority_queue slist

2015-03-16 21:37 363 查看
//

// 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 =
0;

for(; node != 0; 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(0){}


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



//clear()是循环删除所有节点
~slist() {clear();}


iterator begin() {return iterator((list_node*)head.next);}



//强制转化一个0为iterator类型表示end

//最开始的时候,head.next等于0
表示末尾;
iterator end() {return iterator(0);}
size_type size()
const {return __slist_size(head.next);}

bool empty() const {return head.next ==
0;}



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

*/










}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: