一、存储结构
栈是一种线性结构:先进后出,可用数组与链表两种方式来实现。
1.数组栈
用数组来实现栈(此处用int[]为例)。
- 用一个数组存放栈中元素,有一个栈顶指针
- 提供的方法:
// 将元素data入栈
public void push(int data)
// 返回并删除栈顶元素
public int pop()
// 返回栈顶元素
public int peek():
// 判断栈是否为空
public boolean isEmpty()
- 栈满不入栈(或扩充容量后入栈),栈空不出栈(栈空时抛出EmptyStackException)
1.1以int[]为例实现
import java.util.Arrays;
import java.util.EmptyStackException;
/**
*
* Description:栈:基于数组、int[] 实现
* @author 杨丽金
* @date 2018-3-31
* @version 1.0
*/
public class MyStack_array {
int[] stack;
// 栈顶指针
int top=-1;
public MyStack_array(){
// 初始化栈容量为5
stack=new int[5];
}
/**
* 入栈操作
* @param data
*/
public void push(int data){
ensureCapacity();
stack[++top]=data;
}
private void ensureCapacity() {
if(top==stack.length-1){
// 栈满
int newLength=stack.length*2;
stack=Arrays.copyOf(stack, newLength);
}
}
/**
* 取栈顶元素
* @return
* @throws Exception
*/
public int peek(){
if(!isEmpty()){
return stack[top];
}else{
throw new EmptyStackException();
}
}
public boolean isEmpty() {
if(top==-1){
return true;
}
return false;
}
/**
* 返回并删除栈顶元素
* @throws Exception
*/
public int pop(){
int i=peek();
top--;
return i;
}
/**
* 打印栈中元素
*/
public void printStack(){
// for(int i=0;i<=top;i++){
// System.out.print(stack[i]+" ");
// }
System.out.println(Arrays.toString(stack));
}
public static void main(String[] args) {
MyStack_array s=new MyStack_array();
s.push(1);
s.push(2);
s.push(3);
s.push(4);
System.out.println("栈未扩充空间时:");
s.printStack();
try {
System.out.println("栈顶元素为:"+s.peek());
} catch (Exception e) {
System.out.println("栈空,无栈顶元素");
}
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
s.push(6);
s.push(7);
s.push(8);
s.push(9);
s.push(10);
System.out.println("栈扩充空间时:");
s.printStack();
try {
System.out.println("栈顶元素为:"+s.peek());
} catch (Exception e) {
System.out.println("栈空,无栈顶元素");
}
}
}
1.2在上述基础上改造成泛型栈
/**
*
* Description:栈:基于数组、泛型 实现
* @author 杨丽金
* @date 2018-3-31
* @version 1.0
*/
public class MyStack_array_generic {
// 默认栈容量大小
private static final int DEFAULT_SIZE = 3;
// 存储栈中元素
private E[] stack;
// 栈顶指针
private int top=-1;
public MyStack_array_generic(Class type){
this(type,DEFAULT_SIZE);
}
public MyStack_array_generic(Class type,int size){
// 构造函数中完成相关初始化操作
// 不能直接使用stack=new E[DEFAULT_SIZE];
stack=(E[]) Array.newInstance(type, size);
}
/**
* 入栈
* @param data
*/
public void push(E data){
ensureCapacity();
stack[++top]=data;
}
private void ensureCapacity() {
if(top==stack.length-1){
int newLength=stack.length*2;
stack=Arrays.copyOf(stack, newLength);
}
}
/**
* 返回并删除栈顶元素
* @return
* @throws Exception
*/
public E pop(){
E obj=peek();
top--;
return obj;
}
private boolean isEmpty() {
if(top==stack.length){
return true;
}
return false;
}
/**
* 取栈顶元素
* @return
* @throws Exception
*/
public E peek(){
if(isEmpty()){
throw new EmptyStackException();
}else{
return stack[top];
}
}
public void printStack(){
System.out.println(Arrays.toString(stack));
}
public static void main(String[] args) {
MyStack_array_generic s=new MyStack_array_generic(Person.class);
s.push(new Person(10,"小红"));
s.push(new Person(20,"小名"));
s.push(new Person(30,"小李"));
System.out.println("栈未扩充空间时:");
s.printStack();
try {
System.out.println("栈顶元素为:"+s.peek());
} catch (Exception e) {
System.out.println("栈空,无栈顶元素");
}
s.push(new Person(10,"小红"));
s.push(new Person(20,"小名"));
s.push(new Person(30,"小李"));
s.push(new Person(10,"haha"));
s.push(new Person(20,"wwaa"));
s.push(new Person(30,"caca"));
s.push(new Person(30,"dfs"));
System.out.println("栈扩充空间时:");
s.printStack();
try {
System.out.println("栈顶元素为:"+s.peek());
} catch (Exception e) {
System.out.println("栈空,无栈顶元素");
}
}
}
class Person{
int age;
String name;
public Person(int age,String name){
this.age=age;
this.name=name;
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
}
2.链表栈
用链表存储栈,链表栈的实现使用的是链表的头插法;
import java.util.EmptyStackException;
/**
*
*
* Description:用链表实现队列
*
*
* @author 杨丽金
* @date 2018-3-31
* @version 1.0
*/
public class MyStack_linkedList {
// 栈顶指针
private Node top = null;
// 将元素data入栈
public void push(E data) {
Node newNode = new Node(data);
if (isEmpty()) {
top = newNode;
} else {
// 利用链表的头插法
newNode.next = top;
top = newNode;
}
}
// 返回并删除栈顶元素
public E pop() {
if (top == null) {
throw new EmptyStackException();
} else {
Node ret = top;
top = top.next;
return ret.data;
}
}
// 返回栈顶元素
public E peek() {
if (top == null) {
throw new EmptyStackException();
} else {
return top.data;
}
}
// 判断栈是否为空
public boolean isEmpty() {
return top == null;
}
/**
* 打印栈中元素
*/
public void printStack() {
Node cur = top;
// 循环最重要的是:循环条件+迭代条件!!
while (cur != null) {// 循环条件
System.out.print(cur.data + " ");
cur = cur.next;// 迭代条件
}
System.out.println();
}
class Node {
E data;
Node next;
public Node(E data) {
this.data = data;
next = null;
}
}
public static void main(String[] args) {
MyStack_linkedList s = new MyStack_linkedList();
try {
System.out.println("栈顶元素为:" + s.peek());
} catch (Exception e) {
System.out.println("栈空,无栈顶元素");
}
s.push(new Person(10, "小红"));
s.push(new Person(20, "小名"));
s.push(new Person(30, "小李"));
s.push(new Person(10, "haha"));
s.push(new Person(20, "wwaa"));
s.push(new Person(30, "caca"));
s.push(new Person(30, "dfs"));
s.printStack();
try {
System.out.println("栈顶元素为:" + s.peek());
} catch (Exception e) {
System.out.println("栈空,无栈顶元素");
}
}
}
二、 栈的应用
- 括号匹配
- 后缀表达式
- 栈在递归中的应用