赞
踩
else{ //空间不够用了
insert_aux(end(),x); //更底层了,看上面那张图
}
}
注意:一旦引起空间重新配置,指向原Vector的所有迭代器都将失效!!!
pop_back() 删除末端元素:
void pop_back(){
–finish;
destroy(finish); //这个destory后面讲空间配置器的时候会讲到
//就是这么简单
}
erase() 清除(first,last)中所有元素:
先看图:
iterator erase(iterase first,iterase last){
iterator i = copy(last,finish,first) //copy后面的篇章会有,先克服一下困难
destroy(i,finish);
finish = finish - (last - first);
return first;
}
erase() 清除某个位置上的元素:
iterator erase(iterator position){
if(position +1 != end())
copy(position +1,finish,position)
–finish;
destroy(finish);
return position;
}
clear() 方法:
void clear(){
erase(begin(),end());
}
insert() 插入操作:
这个操作的代码实在是太多的底层细节了,还是看图吧:
Vector可以用数组的知识来覆盖,那么List,就用链表的知识来覆盖吧。
这里要注意:
list对于任何元素的插入和删除,永远都是常数时间,我也得去一探究竟啦,我当初回答错了。
先看看数据结构:
template
struct __list_node{
typedef void* void_pointer;
void_pointer prev;
void_pointer next;
T data;
}
双向链表!!!
list的迭代器和vector的不同,它的要求更高一些。因为链表使用的存储空间往往是零零散散的,所以list的迭代器必须有能力在杂乱的存储空间中快速的跳转。
相对于Vector,List还有一个优势,就是不论如何的插入和接合操作,都不会造成原有的List迭代器失效。List的删除操作也只有指向那个被删除的元素的迭代器失效,其它迭代器不会受影响。
SGI list不仅仅是一个双向链表,还是个环状双向链表,所以它只需要一个指针,便可以完整的表现链表。
template <class T,class Alloc = alloc> //缺省使用alloc作为配置器
class list{
protected:
typedef __list_node list_node;
public:
typedef list_node* link_type;
protected:
link_type node; //只要一个指针,便可以表示整个循环链表
如果让指针node指向刻意置于尾端的一个空白节点,node便能符合STL对于“前闭后开”的区间要求,成为list迭代器。
iterator begin(){return (link_type)((*node).next);}
iterator end(){return node;}
bool empty() const{return node->next == node;}
size_type size() const{
size_type result = 0;
disance(begin(),end(),result); //一个全局函数
return result;
}
reference front(){return *begin();}
reference back(){return *–end();}
关于list的增删改查,其实跟链表也就差不多了。
vector是单向开口的连续线性空间,deque则是一种双向开口的连续线性空间。
所谓双向开口,也就是说可以在头尾两端进行插入和删除操作。
vector当然也可以做头部操作,但是其头部操作效率奇差!!!
无法被接受。
(这点以前居然都没有发现!!!)
deque没有所谓容量的观念,因为它是动态的以分段连续空间组合而成,随时可以增加一段新的空间并链接起来。因此,deque没有必要提供所谓的空间保留功能。
但是呢,为什么我们更多的选用vector而非deque呢?因为它的指针实在是太麻烦了。我们后面就知道了。
除非必要,我们应尽可能的选择使用vector而非deque。对deque进行的排序操作,为了最高效率,可以将deque完整的复制到一个vector身上,将vector排序后,再复制回deque。
不要被事务的表面现象锁迷惑,你看它是分段连续线性空间,就以为它是vector和list的结合体,取长补短?其实不然。
为了维持整体连续的假象,数据结构的设计及迭代器前进后退等操作都颇为繁琐。
deque采用一块所谓的map映射,来看吧:
template <class T,class Alloc = alloc,size_t BufSiz = 0>
class deque{
public:
typedef T value_type;
typedef value_type* pointer;
···
protected:
//元素的指针的指针
typedef pointer* map_pointer;
protected:
map_pointer map;
//指向map,map是块连续空间,其内的每个元素都是一个指针,指向一块缓冲区
size_type map_size;
//map内可容纳多少指针
}
看得我尴尬症都犯了。
此外,deque还维护start、finish两个迭代器,分别指向第一缓冲区的第一个元素和最后缓冲区的最后一个元素(的下一个位置)。
此外,它当然也必须记住目前map的大小,一旦map的空间不足,必须要重新配置一个更大的map。
什么是栈?怎么说呢,我觉得我真应该先写数据结构专栏。失策失策!!!
栈是一种先进后出的数据结构,它只有一个接口。
只能从一端加入元素,从那一端移除元素,所以并不被允许有其他方法来存取元素。
换言之,stack不允许有遍历行为。
将元素推入stack的方式称为push,将元素退出stack的操作称为pop。
以某种既有容器作为底部结构,将其接口改变,使之符合“先进后出”的特性,形成一个stack,是很容易做到的。
deque是双向开口数据结构,若以deque为底部结构并封闭其头端开口。
便轻而易举形成了一个stack、
(不知道为什么,我觉得好糟糕哦,vector是不能做吗?)
还是等我过两篇写数据结构的时候再说吧。
除deque之外,list也是双向开口的数据结构。以list为底的stack被称作链栈。
嘿我就挺纳闷儿,为什么就非要双向开口的数据结构???
队列,是一种先进先出结构,只能从一端加入元素,从另一端移除元素,所以并不被允许有其他方法来存取元素。
换言之,queue不允许有遍历行为。
那这个跟上面的stack其实没多大区别,只不过一个是后进先出,一个是先进先出的罢了。那为什么也要双向开口的数据结构呢?
heap并不属于STL容器组件,它是个“幕后白手”,扮演priority queue的助手。
顾名思义,那个queue允许用户以任何次序插入数据,但是在插入的时候会根据优先级进行排序,以保证取出的时候是按照优先级排序的。
如果以List作为这个优先级队列的底层机制,那么排序将会很麻烦,如果以二叉搜索树的话,未免大材小用了。
而难度夹在中间的binary heap便是不二人选了。
所谓binary heap,就是一种完全二叉树,整棵树除了底层节点外,都是填满的,从左至右又不得又间隙。
苍白无力的文字啊,来看张图实在:
简单明了吧,可以用想象下面有一个数组来存储所有节点,以树根节点作为数组的[0]位置,可以发现,任何一个节点 [i] 的左子节点必位于 [2i] 处,其右子节点必位于 [2i+1] 处。
而任何一个节点 [k],其父节点必位于 [k/2] 处。
通过这简单的规则,咱就种了一棵树,完全二叉树。
而这颗二叉树需要能动态的增加节点,所以采用vector作为这棵树的底层土壤是个理想的选择。
根据元素排列方式,heap可以分为max-heap和min-heap。STL供应的是max-heap,最大值在头结点。
push_heap算法(尾端插入元素)
本来是自己画了图,但是理解了书中的图之后,发现他的图更有一番风味。
原先我也疑惑于为何同一级中左边的节点会比右边节点大,后来我想明白了。
在插入过程中,这个顺序被打乱是难以避免的,况且这个排序于取出数据并无影响,所以没必要在做额外工作对树的底层做那么精细的排序。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
Java面试核心知识点笔记
其中囊括了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。
Java中高级面试高频考点整理
最后分享Java进阶学习及面试必备的视频教学
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
据库、数据结构等大量知识点。
[外链图片转存中…(img-3JAEcjO4-1712437937712)]
Java中高级面试高频考点整理
[外链图片转存中…(img-GF1GVVIr-1712437937712)]
[外链图片转存中…(img-FVHUTOv9-1712437937712)]
最后分享Java进阶学习及面试必备的视频教学
[外链图片转存中…(img-Ql6d6XWD-1712437937713)]
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。