1.什么是栈
栈是线性表的一种特殊表现形式,与队列的“先进先出”原则不同,栈的处理原则是“后进先出(Last in First out, LIFO)”。
过程理解:①向只有一个门的仓库存取货物的过程(后入库的货物必须先取出);②叠罗汉的过程(最后叠上的罗汉必须先取下)。
2.栈的基本操作
入栈(push):将数据保存到栈顶。入栈时,让栈顶索引移动到栈顶元素的位置即可。
出栈(pop):将栈顶数据弹出。出栈时,先将栈顶元素保存,再将栈顶索引移动到栈顶元素的下一个元素即可。
3.栈的实现
实现方式:数组实现、链表实现
下面给出栈的数组实现代码:
/**
* Created by Hzc on 2019/1/29.
* 栈的可能实现方式与队列相同,可以是数组实现、顺序表实现、链表实现
* 最简单的实现方式是链表实现,但空间浪费比较大
* 最复杂的实现方式是数组/顺序表实现,当数据量比较大时可以很好地节约内存空间
* 这里采用数组实现,实现的思想参考下面代码中的注释
* 另外两种实现方式不写
*
* 栈需要实现的方法:
* isEmpty():判断栈是否为空。栈为空的条件:栈顶索引 top 为 0。
* isFull():判断栈是否满。这个方法只有数组实现才需要,链式实现不需要。栈满的条件:栈顶索引 top 为 MAXSIZE。
* clear():清空栈。清空方法:将栈顶索引 top 设置为 0。
* push(Type):将数据入栈。入栈方法:先将数据放到栈顶索引 top 处,再将栈顶索引 top + 1。
* pop():将栈顶数据出栈。出栈方法:先将栈顶索引 top - 1,再将栈顶数据返回。
* top():返回栈顶数据,但不将栈顶数据出栈。
* height():获取栈的高度。栈顶索引的大小即为栈顶高度。
* 需要注意的是:我实现时,栈顶索引比实际栈顶的索引要大1。例如,栈顶索引 top=1时,实际栈顶为stack[0],此时栈里只有这一个元素。
*/
public class Stack <Type> {
/**
* stack:用作栈的数组
* MAXSIZE:栈的最大高度
* top:栈顶索引
*/
private Type[] stack;//用作队列的数组
private static final int MAXSIZE = 20;//栈的最大高度
private int top;//栈顶索引
/**
* 两种构造方法
*/
public Stack(){//默认空构造方法
stack = (Type[]) new Object[MAXSIZE];
top = 0;//初始时,栈顶为 0
}
public Stack(Type[] list){//根据元素列表构造栈的构造方法
stack = list;
top = list.length-1;//初始时,栈顶为列表的最后一个元素
}
/**
* 判断栈是否为空
* @return 栈是否为空
*/
public boolean isEmpty(){
if ((top == 0))//栈空的条件:栈最底处为空
//链表实现时,栈空的条件:链表头为空
return true;
return false;
}
/**
* 判断栈是否满
* @return 栈是否满
*/
public boolean isFull(){
if (top == MAXSIZE)//栈满的条件:栈顶到达数组最末端
//一般情况下,链表不存在栈满的情况
return true;
return false;
}
/**
* 清空栈
*/
public void clear(){
if (isEmpty())
return;
top = 0;//将栈顶索引移动到 0 处
}
/**
* 将数据入栈
* @param data:需要入栈的数据
* @return 入栈是否成功
*/
public boolean push(Type data){
if (isFull())//栈满,不能入栈
return false;
else
stack[top++] = data;//把数据放入新栈顶索引位置,再将栈顶索引递增 1
return true;
}
/**
* 将栈顶数据出栈
* @return 出栈的数据
*/
public Type pop(){
if (isEmpty())//栈空,不能出栈
return null;
return stack[--top];
}
/**
* 获取栈顶元素
* @return 栈顶元素
*/
public Type top(){
if (isEmpty())//栈空,没有元素
return null;
return stack[top-1];//返回栈顶数据即可
}
/**
* 获取栈的高度
* @return 栈的高度
*/
public int height(){
return top;//栈顶索引是实际栈顶索引+1,因此栈顶索引的大小即为栈的高度
/**
*
* +-------------+
* | null |
* | null |
* | null | ← 栈顶索引 top = 1
* | data = 1 | ← 实际栈顶
* +-------------+
*/
}
/**
* 打印栈里的数据,仅用于测试
*/
public void display(){
System.out.print("从栈顶向栈底打印:");
for (int i = top-1; i >= 0; i--) {
System.out.print(" " + stack[i]);
}
System.out.println();
}
}
下面是栈的测试代码:
public class StackTest {
private Stack<Integer> stack;
private static final int MULTI = 6;
private static final int SIZE = 10;
private static final int POP = 5;
public static void main(String[] args) {
StackTest s = new StackTest();
s.run();
}
public void run(){
stack = new Stack<>();
testPush();
testPop();
System.out.println("------再入栈数据------");
System.out.println("入栈:0");
stack.push(0);
stack.display();
testGetTop();
testGetHeight();
testClear();
}
public void testPush(){
System.out.println("------测试push()方法------");
for (int i = 0; i < SIZE; i++) {
stack.push(i*MULTI);
}
stack.display();
}
public void testPop(){
System.out.println("------测试pop()方法------");
for (int i = 0; i < POP; i++) {
System.out.println("出栈:" + stack.pop());
}
stack.display();
}
public void testGetTop(){
System.out.println("------测试getTop()方法------");
System.out.println("当前栈顶元素:" + stack.getTop());
stack.display();
}
public void testGetHeight(){
System.out.println("------测试getHeight()方法------");
System.out.println("当前栈高度:" + stack.getHeight());
stack.display();
}
public void testClear(){
System.out.println("------测试clear()方法------");
stack.clear();
if (stack.isEmpty())
System.out.println("清空成功!");
else
System.out.println("清空失败!");
}
}
代码不够规范,还望多多包涵~/bq