栈是我们常用的数据结构,java中有为我们实现,即Stack
为了更加理解这个数据结构,我们自己来实现一个栈
需要说明的是jdk为我们实现的Stack,有一些不好的地方,我们都知道栈只能push和pop,但是jdk中的Stack是继承Vector,所以Stack有Vector的所有方法,Vector的底层是用数组实现的,因为Vector可以在任意位置加入元素,所以Stack也可以
这是一个很大的缺点。
下面我们上Stack的代码:
class MyStack<T> {
private T[] elemData;
private int size;
private static final int DEFAULT_CAPACITY = 10;
public MyStack() {
elemData = (T[])new Object[10];
size = 0;
}
//判断栈满
public boolean isFull() {
return size >= elemData.length;
}
//判断栈空
public boolean isEmpty() {
return size <= 0;
}
//扩容
private void grow() {
elemData = Arrays.copyOf(elemData,elemData.length*2+2);
}
//入栈
public boolean push(T data) {
if(isFull()) {
grow();
}
elemData[size++] = data;
return true;
}
//出栈
public T pop() {
if(isEmpty()) {
try {
throw new IllegalAccessException("栈空,不可出栈");
} catch (IllegalAccessException e) {
e.printStackTrace();;
}
}
T temp = elemData[--size];
//防止内存泄漏
elemData[size] = null;
return temp;
}
//获得栈顶元素
public T peek() {
if(isEmpty()) {
try {
throw new IllegalAccessException("栈空,无栈顶元素");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return elemData[size-1];
}
//重写toString
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < size; i++) {
builder.append(elemData[i] + " ");
}
return builder.toString();
}
}
注意
1.我们实现的是数组栈,底层是用数组写的,毕竟数组相对链表更熟悉一点,并且还有一个原因是链表复杂,但是却没有体现链表的优点,链表在插入删除时间复杂度O(1),而栈的插入删除都是在栈顶完成的,用数组一样是O(1)。
2.特别注意的一点是内存泄漏,因为我们是用泛型写的,所以数组元素的类型是一个引用类型,而当我们出栈的时候不能直接让size–,如果这样的话会导致该元素仍然被引用,我们的gc就不会回收该资源,所以一定要将这块的引用置空,这样gc在回收堆上没有被引用的对象才会回收该资源。
3.还有就是注意的一些细节点,在入栈需要做扩容判断,出栈看看栈中还有元素吗,栈是一种比较简单的数据结构,注意的点就这么多。如有错误,请评论指出,多谢。