1. 分析:
1. 栈的特点是先进后出
2. 栈就好比一个箱子,先放进去的东西,被压在了箱子底部,需要上面的东西拿出来之后下面的东西才能拿出来。
3. 队列的特点是先入先出
4. 队列就好比排队买票,先排队的先买票,我可不会给你插队的
5. 队列(Queue)是限定只能在一端插入、另一端删除的线性表。允许删除的一端叫做队头(front),允许插入的一端叫做队尾(rear),没有元素的队列称为“空队列”。
2. 栈
1). 定义一个Stack接口
public interface Stack <E>{
void push(E e);
E pop();
E peek();
boolean isEmpty();
int size();
}
2). 定义一个具体实现类ArrayStack
这里是基于前一篇定义的可变长度数组实现的,因为逻辑一样
public class ArrayStack<E> implements Stack<E>{
private Array<E> array;
public ArrayStack(){
this(10);
}
public ArrayStack(int capacity){
array = new Array<>(capacity);
}
//入栈
@Override
public void push(E e) {
array.addFirst(e);
}
//出栈
@Override
public E pop() {
return array.removeFirst();
}
@Override
public E peek() {
return array.getFirst();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
@Override
public int size() {
return array.size();
}
public int getCapacity(){
return array.getCapacity();
}
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("ArrayStack size ").append(size());
sb.append(", capacity ").append(getCapacity());
sb.append("\n");
sb.append("[");
for (int i = 0; i < size(); i++) {
sb.append(array.get(i));
if(i != size() - 1){
sb.append(", ");
}
}
sb.append("]");
sb.append("\n");
return sb.toString();
}
}
3). 栈的实例
给定一个只包括 ‘(‘,’)’,’{‘,’}’,’[‘,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
示例 1:
输入: "()[]{}"
输出: true
示例 2:
输入: "(]"
输出: false
分析:
只要是‘{,[,(’就入栈,不是就出栈,然后进行比较,
如果是匹配的,最后栈一定是空的
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;
}else{
char pop = stack.pop();
if(c == ']' && pop != '[')
return false;
if(c == '}' && pop != '{')
return false;
if(c == ')' && pop != '(')
return false;
}
}
return stack.isEmpty();
}
3. 队列
1)定义一个队列的接口Queue
public interface Queue<E>{
void enqueue(E e);
E dequeue();
E front();
int size();
boolean isEmpty();
}
2)定义一个具体的实现类,实现Queue接口
也是基于前一篇定义的可变长度数组实现的,因为逻辑一样
public class ArrayQueue<E> implements Queue<E>{
private Array<E> array;
public ArrayQueue(int capacity) {
array = new Array<>(capacity);
}
public ArrayQueue() {
array = new Array<>();
}
//入队 队尾入
@Override
public void enqueue(E e) {
array.addLast(e);
}
//出队 对头出
@Override
public E dequeue() {
return array.removeFirst();
}
//获取对头的元素
@Override
public E front() {
return array.getFirst();
}
@Override
public int size() {
return array.size();
}
public int getCapacity(){
return array.getCapacity();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("ArrayQueue size ").append(size());
sb.append(", capacity ").append(getCapacity());
sb.append("\n");
sb.append("front [");
for (int i = 0; i < size(); i++) {
sb.append(array.get(i));
if(i != size() - 1){
sb.append(", ");
}
}
sb.append("] tail");
return sb.toString();
}
}
3. 循环队列
1) 构造方法
private E[] data;
//对头
private int front;
//队尾
private int tail;
private int size;
public LoopQueue(int capacity){
data = (E[]) new Object[capacity + 1] ;
front = 0;
tail = 0;
size = 0;
}
public LoopQueue(){
this(10);
}
2) 入队 对尾插入
@Override
public void enqueue(E e) {
if((tail + 1) % data.length == front){
//扩容
resize(getCapacity() * 2);
}
data[tail] = e;
//因为是循环队列 所以对data.length取余
tail = (tail + 1) % data.length;
size++;
}
3)出队 对头删除
@Override
public E dequeue() {
if(isEmpty())
throw new IllegalArgumentException("数据是空的");
E temp = data[front];
data[front] = null;
//对头出 循环队列 所以对data.length取余
front = (front + 1) % data.length;
size --;
if(size == getCapacity() / 4 && getCapacity() / 2 != 0){
//减少容量
resize(getCapacity() / 2);
}
return temp;
}
4)获取对头元素
@Override
public E front() {
if(isEmpty())
throw new IllegalArgumentException("数据是空的");
return data[front];
}
5) 扩容
private void resize(int newCapacity) {
E[] newData = (E[]) new Object[newCapacity + 1] ;
for (int i = 0; i < size; i++) {
//这里需要注意 front可能不是0 然后需要对data.length取余,循环去取data里面的元素
newData[i] = data[(i + front) % data.length];
}
data = newData;
//扩容后 对头要重置为0
front = 0;
//队尾是队列的size
tail = size;
}
4. 小结
其实主要也是针对数组的操作,不过对于循环队列需要注意取余
5.联系方式
QQ:1509815887