栈
1.栈的概念
一种特殊的线性表,只允许在固定的一端进行插入和删除元素操作,进行插入和删除的一端称为栈顶,另一端称为栈底.元素遵守后进先出的原则
压栈:入数据在栈顶
出栈:出数据在栈顶
以上是栈的原理图,在现实生活中有很多栈的例子,例如弹匣的压子弹和弹出子弹,例如向水杯里的倒入水和从水杯里倒出水,等都是先进后出,单端出入的例子
- 从上图可以看到,Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是Vector是线程安全的
2.栈的使用
2.1栈的实例化
Stack<T> stack=new Stack();//实例化一个元素类型为T的栈
2.2栈的方法
方法 | 功能 |
---|---|
push(x) | 将x压入栈顶,并返回x |
pop() | 将栈顶元素出栈并返回 |
peek() | 获取栈顶元素 |
size() | 获取栈的元素个数(返回int) |
empty() | 检测栈是否为空(返回boolean) |
2.3栈使用范例
public class Test {
public static void main(String[] args) {
Stack<Integer> stack=new Stack();//实例化一个元素类型为Integer的栈
stack.push(1);//向栈里压入三个元素
stack.push(2);
stack.push(3);//此时栈顶为3
stack.pop();//弹出栈顶,此时栈顶为2
System.out.println(stack.peek());//打印栈顶元素,为2
System.out.println(stack.size());//打印栈的大小,为2
System.out.println(stack.empty());//打印栈是否为空,false
}
}
3.栈的实现
栈的实现一般用数组或者链表实现,考虑栈单端出入的特性,我们用数组实现更优,因为数组在尾部加入删除数组时间成本很小,而用链表实现的话用的是尾插法,而尾插每次都要遍历一次链表来找到尾节点,所以链表的时间成本会更大一些
public class MyStack {
int[] array;
int size;//记录栈的大小
public MyStack(){
array = new int[3];
}
public int push(int e){
ensureCapacity();//判断栈满及扩容
array[size++] = e;
return e;
}
public int pop(){
int e = peek();
size--;
return e;
}
public int peek(){
//如果栈为空则抛出异常
if(empty()){
throw new RuntimeException("栈为空,无法获取栈顶元素");
}
return array[size-1];
}
public int size(){
return size;
}
public boolean empty(){
return 0 == size;
}
//如果栈满,则进行扩容
private void ensureCapacity(){
if(size == array.length){
array = Arrays.copyOf(array, size*2);
}
}
}