起飞就起飞

数据结构之数组、栈和队列

Posted on By baixiao

转自zwl同学。

数组

把数据码成一排存放


数组最大的优点:快速查询,scores[2]
数组最好应用于“索引有语意”的情况,但并非所有有语意的情况都适用于数组,如身份证号,原因,太大

向指定位置添加元素


元素后移


删除指定位置元素


这里的第二个100可以置空,可以不置空,不置空也是安全的,因为它无法被访问到


动态扩容



数组简单的复杂度分析

添加操作

addLast(e)     O(1)
addFirst(e)    O(n)
add(index,e)   O(n/2) = O(n)
resize         O(n)
整体来讲添加操作复杂度 O(n)

删除操作

removeLast(e)	  O(1)
removeFirst(e)	  O(n)
remove(index,e)   O(n/2) = O(n)
resize            O(n)
整体来讲添删除操作复杂度 O(n)

修改操作

set(index, e)     O(1)  // 已知索引

查询操作

get(index)      O(1)
contains(e)     O(n)
find(e)         O(n)

均摊复杂度

假设当前capacity = 8,并且每一次添加操作都使用addLast,9次addLast操作,触发resize,总共进行了17次基本操作。
假设capacity = n, n+1次addLast,触发resize,总共进行2n+1次基本操作。
平均,每次addLast操作,进行2次基本操作,这样均摊计算,时间复杂度是O(1)的。

复杂度震荡

resize         O(n)
removeLast时resize过于着急(Eager)
解决方案:Lazy
当size == capacity / 4 时,才将capacity减半

栈 Stack

栈也是一种线性结构
相比数组,栈对应的操作是数组的子集
只能从一端添加元素,也只能从一端取出元素
这一端称为栈顶

栈是一种后进先出的数据结构
Last In First Out(LIFO)

常见应用





栈的复杂度分析

ArrayStack<E>       
void push(E)        O(1) 均摊
E pop()             O(1) 均摊
E peek()            O(1)
int getSize()       O(1)
boolean isEmpty()   O(1)

队列 Queue

队列也是一种线性结构
相比数组,队列对应的操作是数组的子集
只能从一端(队尾)添加元素,只能从另一端(队首)取出元素
队列是一种先进先出的数据结构(先到先得),First In First Out(FIFO)


删除队首元素(a)


删除后


数组队列的复杂度分析

ArrayQueue<E>       
void enqueue(E)     O(1) 均摊
E dequeue()         O(n) // 出队
E front()           O(1)
int getSize()       O(1)
boolean isEmpty()   O(1)

循环队列

front == tail 队列为空




(tail + 1) % c == front 队列满

capacity中,浪费了一个空间


循环队列的复杂度分析

LoopQueue<E>        
void enqueue(E)     O(1) 均摊 
E dequeue()         O(1) 均摊 
E getFront()        O(1) 
int getSize()       O(1) 
boolean isEmpty()   O(1)