栈的简单实现(一)

什么是栈?

栈结构是从数据的运算来分类的,也就是说栈结构具有特殊的运算规则。而从数据的逻辑结构来看,栈结构其实就是一种线性结构。说到线性结构,我们很容易就想到联想到线性结构中的顺序表和链表。而栈也确实鱼这两种结构存在有着不一般的关系,从存储结构来对栈进行划分,栈可以分为两类:

  • 顺序栈结构:用一组地址连续的内存单元依次保存栈中的数据。
  • 链式栈结构:用链表的形式保存栈中的数据。

但无论用何种存储结构的形式来表示栈,我们应当遵循一个原则:后进先出(Last In First Out, LIFO)原则


如上图所示,该栈结构只能在一端进行操作,操作的一端称为栈顶,另一端则称为栈底。一般的栈结构的基本操作有两个:

  1. 入栈(Push):将数据保存到栈顶。
  2. 出栈(Pop):将栈顶的数据弹出(读取后删除)。

这里先用顺序存储结构来实现栈。首先是栈长度不变的顺序栈结构:


代码如下:

package ds.stack;

/**
 * 简单不可变长栈
 * 
 * @author Abyss_CMG
 * 
 * @param <E>
 */
public class Stack<E> {
	private static final int MAX_LENGTH = 50;// 栈的默认最大长度
	private Object[] objData = null; // 存放栈的数据的数组
	private int nTop;// 用于标记栈顶
	private int nLen;// 用于标记栈的最大长度

	/**
	 * 若实例化栈时没有参数,则使用默认长度50初始化栈
	 */
	Stack() {
		this(MAX_LENGTH);
	}

	/**
	 * 实例化栈结构
	 * 
	 * @param nInitSize
	 *            栈的最大长度
	 */
	Stack(int nInitSize) {
		if (nInitSize > 0) {
			objData = new Object[nInitSize];
			nTop = -1;
			nLen = nInitSize;
		} else {
			// throw new IllegalArgumentException("栈的初始化长度不能小于等于0:" +
			// nInitSize);
			System.out.println("栈的初始化长度不能小于等于0:" + nInitSize);
		}
	}

	/**
	 * 获取栈中已存放数据的长度
	 * 
	 * @param stack
	 *            栈的对象引用
	 * @return 获取栈中已存放数据的长度
	 */
	int getSize(Stack<E> stack) {
		return stack.nTop + 1;
	}

	/**
	 * 获取栈的最大长度
	 * 
	 * @param stack
	 *            栈的对象引用
	 * @return 栈的最大长度(初始化时的长度)
	 */
	int getMaxSize(Stack<E> stack) {
		return stack.nLen;
	}

	/**
	 * 判断是否满栈
	 * 
	 * @param stack
	 *            实例化的对象引用
	 * @return 若满栈则返回true,否则返回false
	 */
	boolean isFull(Stack<E> stack) {
		return (getSize(stack) == stack.nLen) ? true : false;
	}

	/**
	 * 判断是否空栈
	 * 
	 * @param stack
	 *            栈的对象引用
	 * @return 若空栈则返回true,否则返回false
	 */
	boolean isEmpty(Stack<E> stack) {
		return (stack.nTop == -1) ? true : false;
	}

	/**
	 * 清空栈,但不释放内存
	 * 
	 * @param stack
	 *            栈的对象引用
	 */
	void clear(Stack<E> stack) {
		if (stack.nTop != -1) {
			stack.nTop = -1;
		}
	}

	/**
	 * 释放栈的内存空间
	 * 
	 * @param stack
	 *            栈的对象引用
	 */
	void free(Stack<E> stack) {
		stack.clear(stack);
		if (stack != null) {
			stack = null;
		}
	}

	/**
	 * 入栈操作
	 * 
	 * @param stack
	 *            栈的对象引用
	 * @param eData
	 *            要压入栈的数据
	 */
	void push(Stack<E> stack, E eData) {
		if (isFull(stack)) {
			// throw new IndexOutOfBoundsException("栈已满,无法入栈");
			System.out.println("栈已满,无法入栈");
			return;
		}
		stack.objData[++stack.nTop] = eData;
		System.out.println(stack.objData[stack.nTop] + "已入栈");
	}

	/**
	 * 将栈顶弹出
	 * 
	 * @param stack
	 *            栈的对象引用
	 * @return 弹出栈顶数据
	 */
	@SuppressWarnings("unchecked")
	E pop(Stack<E> stack) {
		if (isEmpty(stack)) {
			// throw new IndexOutOfBoundsException("栈已空,无法出栈");
			System.out.println("栈已空,无法出栈");
			return null;
		}
		System.out.println(stack.objData[stack.nTop] + "已出栈");
		return (E) stack.objData[stack.nTop--];
	}

	/**
	 * 读取栈顶数据(不弹出)
	 * 
	 * @param stack
	 *            栈的对象引用
	 * @return 返回栈顶元素
	 */
	@SuppressWarnings("unchecked")
	E peek(Stack<E> stack) {
		if (isEmpty(stack)) {
			// throw new IndexOutOfBoundsException("栈已空,无法读取栈顶元素");
			System.out.println("栈已空,无法读取栈顶元素");
			return null;
		}
		System.out.println(stack.objData[stack.nTop] + "已读取");
		return (E) stack.objData[stack.nTop];
	}
}

测试代码:

package ds.stack;

public class Simple {

	public static void main(String[] args) {
		System.out.println("----新建空栈----");
		Stack<String> stack = new Stack<String>(5);
		System.out.println("栈的最大长度:" + stack.getMaxSize(stack));
		System.out.println("栈的现有长度:" + stack.getSize(stack));

		System.out.println("----测试入栈操作----");
		System.out.println("将test1压入栈");
		stack.push(stack, "test1");
		System.out.println("将test2压入栈");
		stack.push(stack, "test2");
		System.out.println("将test3压入栈");
		stack.push(stack, "test3");
		System.out.println("将test4压入栈");
		stack.push(stack, "test4");
		System.out.println("将test5压入栈");
		stack.push(stack, "test5");
		System.out.println("将test6压入栈");
		stack.push(stack, "test6");
		System.out.println("栈的现有长度:" + stack.getSize(stack));

		System.out.println("----测试读取栈顶操作----");
		stack.peek(stack);
		stack.peek(stack);

		System.out.println("----测试出栈操作----");
		System.out.println("栈的现有长度:" + stack.getSize(stack));
		stack.pop(stack);
		System.out.println("栈的现有长度:" + stack.getSize(stack));
		stack.pop(stack);
		System.out.println("栈的现有长度:" + stack.getSize(stack));
		stack.pop(stack);
		System.out.println("栈的现有长度:" + stack.getSize(stack));
		stack.pop(stack);
		System.out.println("栈的现有长度:" + stack.getSize(stack));
		stack.pop(stack);
		System.out.println("栈的现有长度:" + stack.getSize(stack));
		stack.pop(stack);
	}
}

测试结果:

----新建空栈----
栈的最大长度:5
栈的现有长度:0
----测试入栈操作----
将test1压入栈
test1已入栈
将test2压入栈
test2已入栈
将test3压入栈
test3已入栈
将test4压入栈
test4已入栈
将test5压入栈
test5已入栈
将test6压入栈
栈已满,无法入栈
栈的现有长度:5
----测试读取栈顶操作----
test5已读取
test5已读取
----测试出栈操作----
栈的现有长度:5
test5已出栈
栈的现有长度:4
test4已出栈
栈的现有长度:3
test3已出栈
栈的现有长度:2
test2已出栈
栈的现有长度:1
test1已出栈
栈的现有长度:0
栈已空,无法出栈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值