算法与数据结构之基于数组的栈的实现Java版

栈的应用

在这里举几个比较常见的栈应用的例子

  • 子过程的调用,每当在一个函数中调用另一个函数时,就会发生子过程的调用,而这个工程的实现就用到了栈,当程序执行到子函数所在的行时,会将此时的执行信息压入到系统栈中,当执行完子函数后,会将系统栈中的内容出栈,然后接着执行主函数,最常见的例子就是递归的调用。
  • undo操作,也就是撤销操作,ctrl+z,每当我们在编译器输入词汇的时候,编译器会将我们输入的内容压入栈中,栈顶记录着我们最近输入的元素,当我们输错时,想要撤销,那么此时就会将栈顶的元素出栈,从而达到撤销的效果
  • 括号匹配问题,比如我们在用Eclipse时,if,while等,都需要加上括号,当我们在进行嵌套循环时,编译器就需要识别那个括号和那个括号匹配,这是就需要用到栈,关于括号匹配问题详见:190421打卡:有效括号匹配

操作

public interface Stack<E> {
	int getSize(); //元素个数
	boolean isEmpty(); //是否为空
	void push(E e); //入栈
	E pop(); //返回出栈元素
	E peek(); //返回栈顶元素
}

栈的复杂度分析

在这里插入图片描述
其中push和pop操作涉及数组的扩容和缩容,均摊复杂的为O(1)

源码实现

该栈的实现支持扩容和缩容,以下源码中数组Array是引用:
算法与数据结构之动态数组的实现Java版

为了代码结构上的完整性,在上述数组的基础上,添加了两个方法

//获取最后一个位置的元素
	public E getLast() {
		return get(size - 1); //注意这里为什么不写成return data[size - 1],因为这样写缺少对数组下标的判断
	}
	
	//获取第一个位置的元素
	public E getFirst() {
		return get(0);
	}

以下为栈实现的源码

package stack;

public class ArrayStack<E> implements Stack<E> {
	private Array<E> array;
	
	public ArrayStack(int capacity) {
		array = new Array<>(capacity);
	}
	
	public ArrayStack() {
		array = new Array<>();
	}
	
	@Override
	public int getSize() {
		return array.getSize();
	}

	@Override
	public boolean isEmpty() {
		return array.isEmpty();
	}
	
	public int getCapacity() {
		return array.getCapacity();
	}

	@Override
	public void push(E e) {
		array.addLast(e);
	}

	@Override
	public E pop() {
		return array.removeLast();
	}

	@Override
	public E peek() {
		return array.getLast();
	}
	
	@Override
	public String toString() {
		StringBuilder res = new StringBuilder();
		res.append("Stack:");
		res.append("[");
		for(int i = 0; i < array.getSize(); i++) {
			res.append(array.get(i));
			if (i != array.getSize() - 1) {
				res.append(", ");
			}
		}
		
		res.append("] top");
		return res.toString();
	}
	
}

猜你喜欢

转载自blog.csdn.net/qq_42447402/article/details/89456922