栈的相关知识
是一种后进先出的数据。LIFO
栈的相关应用
- 撤销功能
- 程序调用的系统栈
数组实现栈
常用的操作
void push(E e)
E pop()
//看一下栈顶的元素
E peek()
int getSize()
boolean isEmpty()
数组实现的方式
package array;
public class ArrayStack<E> implements Stack<E> {
private MyArray<E> myArray;
//内部构造,主要是给内部做事情的进行初始化
public ArrayStack(int capcity) {
myArray = new MyArray<>(capcity);
}
public ArrayStack() {
this(10);
}
@Override
public void push(E e) {
myArray.addLast(e);
}
@Override
public E pop() {
return myArray.removeLast();
}
@Override
public E peek() {
return myArray.get(myArray.getSize() - 1);
}
@Override
public int getSize() {
return myArray.getSize();
}
@Override
public boolean isEmpty() {
return myArray.isEmpty();
}
public int getCapcity() {
return myArray.getCapacity();
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("stackSize=" + getSize() + '\n');
for (int i = 0; i < getSize(); i++) {
stringBuilder.append(myArray.get(i) + ", ");
}
stringBuilder.append(" top");
return stringBuilder.toString();
}
}
LeetCode相关题目
20号 给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
Character charAt = s.charAt(i);
if(charAt=='('||charAt=='{'||charAt=='['){
stack.push(charAt);
}else {
if(stack.isEmpty()){
return false;
}
if (charAt ==')'&&stack.pop()!='(') {
return false;
}
if (charAt =='}'&&stack.pop()!='{') {
return false;
}
if (charAt ==']'&&stack.pop()!='[') {
return false;
}
}
}
//循环结束后如果栈为空说明匹配
return stack.isEmpty();
}
队列的相关知识
队列是一种先进先出的数据结构 FIFO
相关接口的方法
void enqueue(E e);
E dequeue();
//看一下队首的元素
E getFront();
int getSize();
boolean isEmpty();
数组实现队列
public class ArrayQueue<E> implements Queue<E> {
private MyArray<E> myArray;
public ArrayQueue(int capcity) {
myArray = new MyArray<>(capcity);
}
public ArrayQueue() {
this(10);
}
@Override
public void enqueue(E e) {
myArray.addLast(e);
}
@Override
public E dequeue() {
return myArray.remove(0);
}
@Override
public E getFront() {
return myArray.get(0);
}
@Override
public int getSize() {
return myArray.getSize();
}
@Override
public boolean isEmpty() {
return myArray.isEmpty();
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("top [");
for (int i = 0; i < getSize(); i++) {
stringBuilder.append(myArray.get(i) + ", ");
}
stringBuilder.append("] end");
return stringBuilder.toString();
}
}
缺点就是在入队的时候时间复杂度为O(n) 可以使用循环队列来改善这个情况。可以做到入队时间复杂度为O(1)
对于循环队列设置一个start和end,此时还有一个size,start指向要出去的数据的索引,end执行即将要添加位置的索引。这个size可以让start和end进行解耦,取数和加数值需要看size是否为0或者是否已经满了。size很重要!!!
@Override
public void push(E e) {
if (size==data.length){
throw new RuntimeException("超出泛微");
}
size++;
data[tail%data.length] = e;
}
@Override
public E pop() {
if (size==0){
throw new RuntimeException("为空,不能弹出");
}
E e = data[front % this.data.length];
front++;
size--;
return e;
}
此时也可以考虑容量不足的时候进行扩容,也可以进行缩容。如下
private void resize(int newCapacity){
E[] newData = (E[])new Object[newCapacity];
for(int i = 0 ; i < size ; i ++)
newData[i] = data[(i + front) % data.length];
data = newData;
front = 0;
tail = size;
}