1.栈
栈是一种操作受限的线性表,只允许从一端插入和删除数据,拥有先进后出的特点。
一般而言,把允许操作的一端称为栈顶(Top),不可操作的一端称为栈底(Bottom),同时把插入元素的操作称为入栈或压栈(Push),删除元素的操作称为出栈(Pop)。若栈中没有任何元素,则称为空栈,栈的结构图如下:入栈顺序为1,2,3。出栈的顺序为3,2,1。
栈的常用操作主要有:
- push(E):增加一个元素E
- pop():弹出元素E
- peek():显示栈顶元素,但是不出栈
- empty():判断栈是否为空
2.基于数组实现栈
在应用时要注意每次入栈之前都要判断站的容量是否够用,如果不够则进行扩容。此处我们将top指向栈顶的空元素。
入栈的过程如下图所示:
出栈的过程如下图所示:
具体代码如下:
class MyStack<T>{
//初始化栈的容量为30
Object[] stack = new Object[30];
int top;
//判断栈是否为空,为空者返回true
public boolean empty() {
return top == 0;
}
//返回栈顶元素
public T peek() {
T t = null;
if(!empty()) {
t = (T)stack[top-1];
}
return t;
}
//入栈
public void push(T t) {
expendCapacity(top+1);
stack[top] = t;
top++;
}
//出栈
public T pop() {
T t= peek();
if(!empty()) {
stack[top-1] = null;
top--;
}
return t;
}
//扩大容量
public void expendCapacity(int size) {
int len = stack.length;
if(size>len) {
size = size*3/2+1;//每次扩大50%
stack = Arrays.copyOf(stack, size);
}
}
3.基于链表实现栈
使用链表实现站时,插入和删除都是在头结点的位置。
具体实现代码如下:
class ListStack<T>{
//定义链表结点
class Node<T>{
T t;
Node next;
}
//构造头节点
Node<T> head;
//使用构造函数,初始化头节点
public ListStack() {
head = null;
}
//入栈
public void Push(T t) {
if(t == null) {
throw new NullPointerException("参数不能为空");
}
if(head == null) {
head = new Node<T>();
head.t = t;
head.next = null;
}else {
Node<T> temp = head;
head = new Node<T>();
head.t =t;
head.next = temp;
}
}
//出栈
public T pop() {
if(head == null) {
return null;
}
T t = head.t;
head = head.next;
return t;
}
//取栈顶元素
public T peek() {
if(head == null) {
return null;
}
return head.t;
}
//判断栈是否为空,为空则返回true
public boolean empty(){
if(head == null) {
return true;
}else {
return false;
}
}
}