目录
栈和队列使操作受限制的线性表,本质上栈和队列没啥不同,可以相互转换。
一、栈
1.1概念
栈:一种特殊的线性表,其只允许在指定的一端进行查如何删除元素操作,进行数据插入和删除操作的一端称为栈顶,另一端称为栈底,栈中的数据元素遵守后进先出(LIFO)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,push。
出栈:栈的删除操作叫做出栈,pop。
查看栈顶元素peek,只取值,不删除。
栈的实现根据实用的内部结构不同分为顺序栈和链式栈,顺序栈的内部还是动态数组,规定只能从数组的末尾进行插入和删除,链式栈的内部是链表,规定在链表的尾部进行插入和删除。
1.2实现顺序栈
顺序栈的基础构造和动态数组几乎完全一样。主要实现四个方法,pop,push,peek,toString。
push方法就是相当于动态数组的尾插法,也要考虑到是否扩容。pop方法就是在在栈中有存储时也就是size!=0,存储最后一位元素然后把它删除并且返回。peek就是返回最后一位元素的值不进行其他操作。
public class stack {
private int size;
private int[] data;
public stack(){
this(10);
}
public stack(int capacity){
this.data = new int[capacity];
}
public void push(int val){
this.data[size] = val;
size++;
if(size>data.length){
this.data = Arrays.copyOf(data,data.length>>1);
}
}
public int pop() throws NoSuchFieldException {
if(size ==0){
throw new NoSuchFieldException("stack is Null!");
}
int i = this.data[size-1];
size--;
return i;
}
public int peek() throws NoSuchFieldException {
if(size ==0){
throw new NoSuchFieldException("stack is Null!");
}
int i = this.data[size-1];
return i;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
for(int i = 0;i<size;i++){
sb.append(this.data[i]);
if(i==size-1){
sb.append("]");
}else{
sb.append(",");
}
}
return sb.toString();
}
}
public class stackTest {
public static void main(String[] args) throws NoSuchFieldException {
stack s = new stack();
s.push(1);
s.push(3);
s.push(5);
s.push(7);
System.out.println(s.toString());
System.out.println(s.pop());
System.out.println(s.peek());
System.out.println(s.toString());
}
}
首先插入1,3,5,7。然后调用toString展示栈,在调用pop,显示最后一位元素并且删除,在调用peek查看新的最后一位元素, 再调用toString展示栈。
1.3JDK中的栈的应用
JDK中的栈是一个具体的类Stack,主要方法就是pop,push,peek。
(1)用栈实现链表的倒序输出
只需要把每一项链表的值一个个存储到栈中,然后直到栈空,再停止输出。运用了栈的后进先出的特点。
public void printReverseByStack(){
Stack<Integer> s = new Stack<>();
Node node = head;
while(node != null){
s.push(node.val);
node = node.next;
}
while (!s.empty()){
System.out.print(s.pop()+"->");
if(s.empty()){
System.out.println("NULL");
}
}
}
public static void main(String[] args) {
LinkedListR list = new LinkedListR();
list.addFirst(1);
list.addFirst(3);
list.add(5);
list.add(7);
list.add(1,10);
list.print();
list.printReverseByStack();
}
(2)最小栈
一个栈是解决不了的,top和getMin是两个相互独立的方法,top返回当前栈顶元素,getMin在O(1)返回最小值。
所以我们创建两个栈,real用于实际存储元素,min用于存储最小值并且保证栈顶元素一定是real中的最小值。
首先第一个元素是-2,直接入real栈,然后判断min栈是否为空,如果是空就直接将元素入min栈。