1.栈的定义
栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。
(1)通常称插入、删除的这一端为栈顶 (Top),另一端称为栈底 (Bottom)。
(2)当表中没有元素时称为空栈。
(3)栈为后进先出(Last In First Out)的线性表,简称为 LIFO 表。
栈的修改是按后进先出的原则进行。每次删除(退栈)的总是当前栈中" 最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除。
【示例】元素是以a1,a2,…,an的顺序进栈,退栈的次序却是an,an-1,…, a1。
2.栈的基本运算
(1)InitStack(S)
构造一个空栈S。
(2)StackEmpty(S)
判栈空。若S为空栈,则返回TRUE,否则返回FALSE。
(3)StackFull(S)
判栈满。若S为满栈,则返回TRUE,否则返回FALSE。
注意: 该运算只适用于栈的顺序存储结构。
(4)Push(S,x)
进栈。若栈S不满,则将元素x插入S的栈顶。
(5)Pop(S)
3.数组实现(即栈的顺序存储结构)
package unit4Stack;
/**
* <p>Title: StackType</p>
* <p>Description: </p>
* <p>Company: </p>
* @author 夏 杰
* @date 2015年12月10日 下午11:43:17
* @vesion 1.0
*/
public class StackType {
//底层是一个数组(也可以是一个对象数组)
private long[] arr;
//栈顶指针
private int top ;
/**
*默认的构造方法
*/
public StackType() {
arr = new long[10];
top = -1 ;
}
/**
*带参数的构造方法,参数为数据初始化的大小
*/
public StackType(int maxsize) {
arr = new long[maxsize];
top = -1;
}
/**
* 添加数据
* @param value
*/
public void push (int value){
//注:++top,和top++是有区别的
arr[++top] = value;
}
/**
* 获取栈顶数据,并移除数据
* @param value
*/
public long pop (){
//注:--top,和top--是有区别的
return arr[top--];
}
/**
* 查看栈顶数据
* @param value
* @return
*/
public long peek (){
//注:--top,和top--是有区别的
return arr[top];
}
/**
* 判断是否为空
* @return
*/
public boolean isEmpty(){
if(top == -1){
return true;
}else{
return false;
}
}
/**
* 判断是否满了
* @return
*/
public boolean isFull(){
return top == arr.length - 1;
}
}
public class TestTask {
public static void main(String[] args) {
StackType stack = new StackType(4);
stack.push(25);
stack.push(5);
stack.push(33);
System.out.println(stack.peek());
}
}
4.链栈的实现(即栈的链式存储结构)
顺序栈的缺点:
为了保证不溢出,必须事先给栈分配一个较大的连续的内存空间,这显然浪费了存储空间,而且在很多时候并不能保证所分配的空间一定够用,这大大的降低了顺序栈的可用性,所以采用链式存储结构。
链式栈的优点:
可以不用指定大小,也不用必须是连续的内存空间,可以在需要时动态的增加容量,对内存的利用率比较高,不浪费内存存储空间。
链栈的代码实现
定义节点
/**
*
*/
package unit4Stack.linked;
/**
* <p>Title: StackNode</p>
* <p>Description: </p>
* <p>Company: </p>
* @author 夏 杰
* @param <T>
* @date 2015年12月11日 下午9:15:16
* @vesion 1.0
*/
public class StackNode<T> {
T data;
StackNode next;
//无参构造函数
public StackNode(){}
public StackNode(T data, StackNode next) {
this.data = data;
this.next = next;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public StackNode getNext() {
return next;
}
public void setNext(StackNode next) {
this.next = next;
}
}
链表实现
package unit4Stack.linked;
/**
* <p>Title: LinkedStack</p>
* <p>Description: </p>
* <p>Company: </p>
* @author 夏 杰
* @param <T>
* @date 2015年12月11日 下午9:56:01
* @vesion 1.0
*/
public class LinkedStack<T> {
//栈顶元素
private StackNode top;
//元素个数
private int size;
//初始化
public LinkedStack(){
top = null;
size = 0;
}
//插入数据
public void push(T data){
StackNode stackNode = new StackNode();
stackNode.data = data;
stackNode.next = top;
top = stackNode;
}
/**
* 出栈
* 将要出栈的元素删除
* @param <T>
* @return
*/
public T pop(){
//要出栈的原来的top
StackNode oldTop = top;
top = oldTop.next;
//释放要出栈的节点的引用
oldTop.next = null;
size--;
return (T) oldTop.data;
}
/**
* 返回栈顶的元素,但不出栈
*/
public T peek(){
return (T) top.data;
}
}
测试
/**
*
*/
package unit4Stack.linked;
/**
* <p>Title: LinkedStackTest</p>
* <p>Description: </p>
* <p>Company: </p>
* @author 夏 杰
* @date 2015年12月11日 下午10:13:15
* @vesion 1.0
*/
public class LinkedStackTest {
public static void main(String[] args) {
LinkedStack<String> stack = new LinkedStack<String>();
stack.push("aaaa");
stack.push("bbbb");
stack.push("cccc");
stack.push("dddd");
// 访问栈顶元素
System.out.println("访问栈顶元素:" + stack.peek());
// 弹出一个元素
System.out.println("第一次弹出栈顶元素:" + stack.pop());
// 再次弹出一个元素
System.out.println("第二次弹出栈顶元素:" + stack.pop());
}
}