STL源码剖析笔记 —— 第四章

  1. vector
    1.1 构造函数:
    vector():start(0),finish(0),end_of_storage(0){}  //start表示目前使用空间的头,finish表示目前使用空间的尾,end_of_storage表示目前可使用空间的尾
    vector(size_type n,const T& value) {fill_initialize(n,value);}
    void fill_innitialize(size_type n,const T& value)
    {
    	start=allocate_and_fill(n,value);
    	finish=start+n;
    	end_of_storage=finish;
    }
    iterator allocate_and_fill(size_type n,const T& x)
    {
    	iterator result=data_allocator::allocate(n); //配置n个元素空间
    	uninitialized_fill_n(result,n,x); //根据第一形参的型别特性(type traits)决定使用fill_n()或反复调用construct()
    	return result;
    }
    vector(int n,const T& value) {fill_initialize(n,value);}
    vector(long n,const T& value) {fill_initialize(n,value);}
    explicit vector(size_type n) {fill_initialize(n,T());}
    
    1.2 erase
    iterator erase(iterator position) //清除某个位置上的元素
    {
    	if(position +1 != end())
    		copy(position+1,finish,position);
    	--finish;
    	destroy(finish);
    	return position;
    	}
    iterator erase(iterator first, iterator last) //清除[first,last)的所有元素
    {
    	iterator i=copy(last,finish,first);
    	destroy(i,finsih);
    	finish=finish-(last-first);
    	return first;
    	}
    
    1.3 对vector的任何操作,一旦引起空间重新配置,指向元vector的所有迭代器就都失效了
    1.4 vector的insert返回值是void
  2. list
    2.1 list的插入和接合(splice)都不会使原来的迭代器失效,删除也只会使指向被删除元素的迭代器失效
    2.2
    _list_node<T>* node;   //list列表的节点
    T& operator* ()const {return (*node).data;}
    T* operator-> ()const {return &(operator*());} //迭代器的成员存取运算子的标准做法
    
    2.3 list的插入在指定迭代器之前,返回指向新插入元素的迭代器
    2.4 erase删除迭代器的值返回的是该迭代器的next迭代器
    2.5 remove将数值为value的所有元素移除
    template<class T,class Alloc>
    void list<T,Alloc>::remove(const T& value)
    {
    	iterator first=begin();
    	iterator lase=end();
    	while(first!=last)
    	{
    		iterator nexe=first;
    		++next;
    		if(*first==value) erase(first);
    		first=next;
    	}
    }
    
    2.6 移除数值相同的连续元素,注意,只有连续而相同的元素才会被移除剩一个
    2.7 splice
    2.7.1 void splice(iterator position,list& x); //将x接合于position所指位置之前,x必须不同于*this
    2.7.2 void splice(iterator position,list& x,iterator first,iterator last); //将[first,last)接合于position所指位置之前,position和[first,last)可以指向同一个list,但position不能在[first,last)之内
    2.8 merge之前要保证先排好序
  3. deque
    3.1 deque与vector的区别一是deque允许在常数时间内对头端的元素进行插入或删除;二是deque没有容量概念。除非必要,我们应该尽可能使用vector,对deque进行的排序操作,为了提高效率,可将deque先完整复制到一个vector身上,将vector排序后再复制回deque
  4. stack和queue
    4.1 stack和queue没有迭代器,没有遍历功能
    4.2 可以更换容器,比如queue<int,list< int >> iqueue;
  5. binary heap是一种完全二叉树
    5.1 push_heap,将新元素插在底层vector的end()处,将新节点与其父节点比较,如果其键值比父节点大,就父子对换位置,如此一直上溯,直到不需要对换或者到根节点为止
    5.2 pop_heap, STL默认是max-heap,最大值必然在根节点,pop操作取走根节点后,为了满足完全二叉树的条件,必须割舍最下层最右边的叶节点,并将其值重新安插在max-heap。将空间节点和其较大子节点对调,并持续下放,直到叶子节点为止。注意,pop_heap之后,最大元素只是被置于底部容器的最尾端,尚未被取走。如果要取其值,可使用底部容器(vector)的back()函数,如果要移除它,可使用vector提供的pop_back()函数
    5.3 创建大大根堆: 我们假设根节点的索引为1。
    5.3.1.从最后一个非叶子节点为父节点的子树出发,从右往左,从下往上进行调整操作,这里需注意的是:
    a.是以该非叶子节点为父节点的子树,即该父节点以下的所有部分都进行调整操作。
    b.由于是从右往左从下往上,则某一步进行调整时在调整它之前的那些子树已经是堆有序了,即走到某个非叶子节点时,它的子树已经是堆有序了(因为是从下往上)
    5.3.2.即调整函数 :
    a.如果该节点比它的两个孩子节点都大,则该节点不用调整了,因为它的孩子节点也是堆有序 (上面b已说明)
    b.如果该节点比它的两个子节点中的较大节点小,即array[i]<max(array[2i],array[2i+1]),将 array[i]赋给temp,以后每次都跟temp比较。将max(array[2i],array[2i+1])赋给array[i]。接着从max(array[2i],array[2i+1]) 对应的那个节点出发,继续进行该操作,直到该节点到达了n。当然每次判断边界条件为左子树的索引小于n,则右子树才有值。
    5.4 priority_queue< int > xxx 大根堆
    priority_queue<int, vector< int >, greater< int >> xxxx 小根堆
  6. slist:单向链表
    6.1 作为一个单向链表,slist没有任何方便的办法可以回头定出前一个位置,因此它必须从头找起。换句话说,除了slist起点附近的区域之外,在其他位置上采用insert或erase操作函数,都属不智之举。
    6.2 slist没有push_back和pop_back ,只有push_front 和 pop_front
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值