一、Stack:
-
2.具体实现:
使用数组实现
public class Stack<E>{private int size;private E[] data;// 直接指定capacitypublic Stack(){data = (E[]) new Object[capacity];size = 0;}// 数组扩容或者缩小public E[] resize(int capacity){E[] temp = (E[]) new Object[capacity];for(int i = 0; i < size; i++){temp[i] = data[i];}data = temp;return data;}// 添加元素public void push(E e){if(size == data.length){resize(2 * data.length);}data[size] = e;size++;}// 获取栈顶元素public E peek(){return data[size - 1];}// 弹出栈顶元素public E pop(){if(size == 0){throw new IlleageArgumentAccess("empty Stack");}E res = data[size - 1];data[size - 1] = null;size--;if(size == (data.length/4 ) && size/2 != 0){resize(data.length/2);}return res;}// 获取数组内元素个数public int getSize(){return size;}public boolean isEmpty(){return size == 0;}}
3.栈中应用的复杂度分析:
- void push O(1) 均摊
- E pop() O(1) 均摊
- E peek() O(1)
- int getSize() O(1)
-
4.括号匹配(编译器):
相关leetcode问题 : https://leetcode-cn.com/problems/valid-parentheses/

class Solution {public boolean isValid(String s) {Stack<Character> stack = new Stack();for(int i = 0; i<s.length();i++){char c = s.charAt(i);if(c == '(' || c == '[' || c=='{'){stack.push(c);}else{if(stack.isEmpty()){return false;}char topChar = stack.pop();if(c == ')' && topChar!='(' || c == '}' && topChar!='{'|| c == ']' && topChar!='['){return false;}}}return stack.isEmpty();}}
二、Queue(队列)
实际上是一个接口,通常由LinkedList 实现
也是数据结构,同样操作也是数组的子集
- 只能从队尾添加元素,从队首取出元素
- 多使用链表实现

队列的各种操作的复杂度分析
- void enqueue(E) O(1) 从尾部添加元素 addLast()
- E dequeue() O(n) 从队首删除元素 removeFirst()
- E front() O(1)
- int getSize() O(1)
boolean isEmpty() O(1)
public class Queue<E>{private int size;private E[] data;public Queue(){data = (E[]) new Object[15];size = 0;}// resize 数组public E[] resize(int capacity){E[] temp = (E[]) new Object[capacity];for(int i = 0; i < size; i++){temp[i] = data[i];}data = temp;return data;}// 入队操作public void enqueue(E e){if(size == data.length){resize(2*data.length);}data[size] = e;size++;}// 出队操作public E dequeue(){if(size == 0){throw new IllegalArgumentException("empty Stack");}E res = data[0];for(int i = 0; i < size - 1; i++){data[i] = data[i+1];}data[size - 1] = data[size];size--;return res;}// 队首元素public E front(){return data[0];}// 获取元素个数public int getSize(){return size;}// 查看是否为空public boolean isEmpty(){return size==0;}// 从尾部添加元素public void addLast(E e){enqueue(e);}// 从队首删除元素public E removeLast(){return dequeue();}}
三、循环队列(记录队首)
front / tail

- front == tail (队列为空) | | (tail + 1) % c == front (队列为满)
对于循环队列的出队操作 dequeue() 复杂度为O (1) ```java // 实现方法 : 1.浪费一个空间 2.不浪费一个空间 // 循环数组需要确定头节点与尾结点,因为此时头和尾不再是 0 和 data.length - 1 public LoopQueue
{ private int size; private E[] data; private int front, tail; public LoopQueue(){
data = (E[]) new Object[15];size = 0;front = 0;tail = 0;
}
// 对数组进行扩容 private E[] resize(int capacity){
E[] temp = (E[]) new Object[capacity];for(int i = 0; i < data.lenght; i++){temp[i] = data[(i+front)%(data.length)];}data = temp;front = 0;tail = data.length - 1;return data;
}
// 队尾入栈 enqueue public void enqueue(E e){
if(size == data.length){resize(2*data.length);}data[tail] = e;tail = (tail + 1) % data.length;size++;
}
// 队首出栈 dequeue public E dequeue(){
if(size == 0){throw new IllegalArgumentException("Queue is empty");}data[front] = null;front = (front + 1) % data.length;size--;if(size == getCapacity() /4 && getCapacity()/2!=0){resize(getCapacity()/2);}return res;
}
// 获得栈内元素个数 public int getSize(){
return size;
}
// 获取队首元素 public E getFirst(){
return data[front];
}
// 获取队尾元素 public E getLast(){
return data[tail];
}
// 查看数组是否为空 public boolean isEmpty(){
return size == 0;
}
}
<a name="8dc02c70"></a>## 四、数组队列与循环队列的复杂度分析实际上 浪费空间使用 size() 是为了,保证 tali == front 时可以判断非空还是非满,假如不使用size 的话如何实现<br />使用无 size进行实现<br />但是实际上,tail != front , 主要是因为, 在 enqueue 的时候, 使用size的是先把元素填进去之后,再改变tail。 假设 capacity = 3, 实际为4;<br />arr [ tail = 0 ] = 1 ; tail ++ = 1; arr [ tail = 1 ] = 2 ; tail ++ = 2;<br />arr [ tail = 2 ] = 3 ; tail ++ = 3; 此时 (tail + 1) % data.length == 0, 进行resize() ; 即 index = 3 的空间没有用到。 此时使用 size 是因为 tail 超前++ ; 存在空值,可以直接使用size++ 计算数量<a name="98848ff9"></a>## 五、双端队列(Deque):可以在两端添加元素,也可以在队列的两端删除元素<br />addFront() / addLast()<br />removeFront() / removeLast()```java// 实现 Dequepublic class Deque<E>{public void addFront(){if(size == data.length){resize(2*data.length);}if(front == 0){front = (front - 1 + data.length);data[front] = e;} else {front = front - 1;data[front] = e;}size++;}public E removeLast(){if(size == 0){throw new IllegalArgumentException("Queue is empty");}E res;if(tail == 0){tail = tail - 1 + data.length;res = data[tail];data[tail] = null;} else {tail = tail - 1;data[tail] = null;}size--;return res;}}
六、使用动态数组实现栈和队列
https://leetcode-cn.com/problems/implement-stack-using-queues/ 用队列实现栈
// 后入先出
class MyStack {
private Queue<Integer> queue1;
private Queue<Integer> queue2;
public MyStack(){
queue1 = new LinkedList<Integer>;
queue2 = new LinkedList<Integer>;
}
public void push(int x){
while(!queue1.isEmpty()){
queue2.add(queue1.poll());
}
queue1.add(x);
while(!queue2.isEmpty()){
queue1.add(queue2.poll());
}
}
public int pop(){
return queue1.poll();
}
public int top(){
return queue1.peek();
}
public boolean empty(){
return queue1.isEmpty();
}
}
https://leetcode-cn.com/problems/implement-queue-using-stacks/ 用栈实现队列
// 先入先出
class MyQueue {
private Stack<Integer> stack;
private Stack<Integer> stack1;
public MyQueue() {
stack = new Stack<Integer>();
stack1 = new Stack<Integer>();
}
public void push(int x) {
while(!stack.isEmpty()){
stack1.add(stack.pop());
}
stack.add(x);
while(!stack1.isEmpty()){
stack.add(stack1.pop());
}
}
public int pop() {
return stack.pop();
}
public int peek() {
return stack.peek();
}
public boolean empty() {
return stack.isEmpty();
}
}

