栈是先进后出的一种数据结构,如图(来自百度):
好,概念不多说,下面我们来看栈基于链表的实现。
什么是链表?如下
public class Node {
int val;
Node next;
Node(int x) {
val = x;
next = null;
}
}
请自行脑补自行车链子,就是一种仅定义前后关系的数据结构,基于链表的这种特点,我们可以实现
出栈(删除栈顶)
入栈(添加栈顶)
判空(检查栈顶元素是否为空)
代码如下:
//通过链表实现
public class Stack {
Node top;
public Node peek() {//查看栈顶对象(不会删除)
if (top != null) {
return top;
}
return null;
}
public Node pop() {//出栈(会删除)
if (top == null) {
return null;
} else {
Node temp = new Node(top.val);
top = top.next;
return temp;
}
}
public void push(Node n) {//入栈
if (n != null) {
n.next = top;
top = n;
}
}
public boolean isEmpty() {
if (top == null) {
return true;
} else {
return false;
}
}
}
基于数组:
//通过数组实现
public class stack {
private int maxSize;// 栈的大小
private int top;
private char[] arr;
public stack(int size) {
maxSize = size;
top = -1;
arr = new char[maxSize];
}
public void push(char value) { // 压入数据
arr[++top] = value;
}
public char pop() { // 弹出数据
return arr[top--];
}
public char peek() { // 访问栈顶元素
return arr[top];
}
public boolean isFull() { // 栈是否满了
return maxSize - 1 == top;
}
public boolean isEmpty() { // 栈是否为空
return top == -1;
}
}
可以看到基于数组和基于链表实现的栈,在某些方法上的异同,反映出了数组和链表的一些特性:
从逻辑结构角度来看
a、 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。
b、链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)
从内存存储角度来看
a、(静态)数组从栈中分配空间, 对于程序员方便快速,但自由度小。
b、 链表从堆中分配空间, 自由度大但申请管理比较麻烦.
效果图: