前言
在最近几天的尝试做题惨遭打击后,我发现我果然是忘的差不多了= =,于是决定将以前oi的基础知识进行一次简单整理,顺便给新博客加点页数ヽ( ̄▽ ̄)ノ。那么现在就从最基础的数据结构开始吧~(这里只谈基本知识无具体应用实例)
数组
O(1)查找 O(n)插入
前缀和
即原数组第一个数到第i个数的和组成的数组,用来解决求区间和的问题,可以拓展到二维平面
差分
即原数组相邻两项的差值数组(或者说差值数组的前缀和为原数组),用来解决区间修改问题,也可拓展到二维
STL
常用的是vector,c++11还有array,具体内容可以点超链接进去看,十分详细,函数不用全记住,平时用到时去查一查用多了就记住了(´▽`)ノ
链表
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个结点或者访问特定编号的结点则需要O(n)(一个一个跳)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)(二分)和O(1)。
双向链表
即每个结点在保存下一结点地址同时保存上一结点地址,这样结点跳转更加灵活只是写起来麻烦一点点
十字链表
即在一个二维平面上一个结点既要记该行中下一个结点也要记该列中下一个结点(还要根据需求记录其他信息)构成十字链表常用于储存稀疏矩阵和图
块状链表
即分块+链表,就是将一段数据按照分块的思想进行分开并暴力维护,同时把各个块看成一个结点用链表连接起来,使可以更方便的整块处理,而且它还可以拓展出许多功能,甚至有时可以实现平衡树的一些功能。但一般情况我们不考虑这种做法,因为这种写法有时过于复杂且时间复杂度一般很难理想(取决于分块大小)。
可持久化块状链表
考虑可持久化就是把修改操作改为创建一个新块(继承原来块的信息),同时记录当前时间的历史版本的块的编号。
STL
单向链表forward_list 双向链表 list
栈
栈是只能在某一端插入和删除的特殊线性表。用桶堆积物品,先堆进来的压在底下,随后一件一件往上堆。取走时,只能从上面一件一件取。堆和取都在顶部进行,底部一般是不动的。
栈就是一种类似桶堆积物品的数据结构,进行删除和插入的一端称栈顶,另一堆称栈底。插入一般称为进栈(PUSH),删除则称为退栈(POP)。 栈也称为后进先出表(LIFO表)。
一个栈可以用定长为N的数组S来表示,用一个栈指针TOP指向栈顶。若TOP=0,表示栈空,TOP=N时栈满。进栈时TOP加1。退栈时TOP减1。当TOP<0时为下溢。栈指针在运算中永远指向栈顶。
单调栈
总的来说就是维护栈内元素单调递增或递减。
维护方法:现有一个新元素要进栈,首先进行判断分两种情况:
- 当新元素在单调性上优于栈顶时(单增栈新元素比栈顶大,单减栈新元素比栈顶小),进栈,top++;
- 当新元素在单调性与栈顶相同(新元素于栈顶相同)或劣于栈顶时(单增栈新元素比栈顶小,单减栈新元素比栈顶大),出栈,top--,然后返回判断直至新元素进栈;
显然由于每个元素只进栈出栈一次,总体时间复杂度O(n)
STL
栈stack
队列
队列是限定在一端进行插入,另一端进行删除特殊线性表。就像排队买东西,排在前面的人买完东西后离开队伍(删除),而后来的人总是排在队伍未尾(插入)。通常把队列的删除和插入分别称为出队和入队。允许出队的一端称为队头(head),允许入队的一端称为队尾(tail)。所有需要进队的数据项,只能从队尾进入,队列中的数据项只能从队头离去。由于总是先入队的元素先出队(先排队的人先买完东西),这种表也称为先进先出(FIFO)表。
循环队列
正常情况下显然当head指针向后跳动会导致前面有一部分空间浪费掉,这是我们考虑使用循环队列,即当tail=n+1时令tail=1(head同理),
当head和tail第二次重合时则队已满之后按溢出处理。但显然我们无法判断head==tail时是队空还是队满故我们可以选择记录队列元素数量或令tail在head前一个的时候为队满。
链式队列
具体来说就是确定一个头结点和尾结点,队空时直接就是头结点→尾结点,出队就是头结点连指向队首所连的结点,入队类似
单调队列
即维护队列内元素单调递增或递减,用于查询序列上固定长度的所有区间的最值(一个一个尝试入队,同时超过长度的出队,队首为最值),可用来优化1D1D动规
优先队列
优先队列中给每个入队的元素加了一个优先级,优先级高的元素先出队。虽然叫做队列但一般是用堆来维护的。(等写到堆的时候再说明实现方法)用处
双端队列
双端队列是限定插入和删除操作在表的两端进行的线性表,大致分为几种:
- 两端均可插入删除,其实就是循环队列的两个指针不一定朝一个方向移动,链式队列更简单了。
- 一端只可插入或一端只可删除
- 从哪一端插入的只可从哪一端删除(两个栈底底相连= =)
STL
队列queue优先队列priority_queue双端队列deque
结语
虽然只是写了这么点但却看了不少资料还用了不少时间呢QAQ,不过感觉做的也不算太差(´▽`)ノ ,之后的较复杂数据结构可能更费劲Orz,不过今天就先到这里吧~