上一小节 :算法与数据结构 其N 数组和链表 的实现
这一小节就讲讲 栈的实现
什么是栈(Stack)?
栈就是一个容器(杯子?碗?随便你想叫什么都行)
先放进去(push)的数据,就只能放在容器底部,最后放进去的数据,就会在最上面。
那我们要获取数据(pop),就只能从最上面的开始拿出来。
如果你只看看,不进去(peek),就只能看到最上面的数据。
Top 就相当于指针吧,用来指向最上面的数据。
我们一般也称这种数据结构为:先进后出
将上面的结构小结下,可以抽象出下面的伪代码
public class Stack(){
int Top; //模拟指针(当然你觉得没有必要也行)
E[] e ;// 容器
Push();//放进去
Pop();//拿出来
Peek(); //知道最上面的数据
....
}
实现栈,可以通过数组和链表两种形式去实现。
通过数组实现栈
public class MyStackArray<E> {
//默认长度
private static int DEFAULT_SIZE ;
//栈顶指针
private int top = 0;
private E[] es;
public MyStackArray(){
clear();
}
public void clear() {
//恢复数组默认长度
top = 0;
DEFAULT_SIZE=10;
es = (E[]) new Object[DEFAULT_SIZE];
}
//是否为空
public boolean isEmpty(){
return size()==0;
}
//长度
public int size(){
return top;
}
//进栈
public void push(E e){
//如果大等于 原始容量,扩容
if(size()>=DEFAULT_SIZE) {
DEFAULT_SIZE *= 2;
E[] newEs = (E[]) new Object[DEFAULT_SIZE];
for (int i = 0; i < top; i++) {
newEs[i] = es[i];
}
es = newEs;
}
es[top++]= e;
}
//出栈
public E pop(){
if(isEmpty()){
throw new ArrayIndexOutOfBoundsException();
}
return es[--top];
}
//查看栈顶元素
public E peek(){
if(isEmpty()){
throw new ArrayIndexOutOfBoundsException();
}
return es[top-1];
}
}
通过链表实现栈
(其实这里就是类似实现了单链表,但是不能从随便插入数据)
//备注1
public class MyStackLinked<E> implements Iterable<E> {
private int theSize;
//栈顶元素
private Node<E> top;
private class Node<E>{
E e;
Node<E> prev;
public Node(E e, Node<E> prev) {
this.e = e;
this.prev = prev;
}
}
public MyStackLinked() {
clear();
}
public void clear(){
top=new Node<>(null,null);
//当然 top = null;也行
theSize = 0;
}
public int size(){
return theSize;
}
public boolean isEmpty(){
return size()==0;
}
public E top(){
return pop(size());
}
public boolean push(E e){
return push(e,size());
}
public Node<E> get(int index){
Node<E> node;
if(index>size() ||index<0){
throw new IndexOutOfBoundsException();
}
node = top;
for(int i=theSize;i>index;i--){
node = top.prev;
}
return node;
}
public boolean push(E e,int size){
if(size<0 || size>size())
throw new IndexOutOfBoundsException();
Node<E> newNode ;
Node<E> oldNode;
//插在顶部
if(size==size()){
top = new Node<>(e,top);
theSize++;
return true;
}else{
//新节点的前驱
newNode = new Node<>(e,get(size-1));
//节点的前驱
oldNode = get(size);
oldNode.prev=newNode;
theSize++;
return true;
}
}
public E pop(int index) {
if(index>size() || index<0)
throw new IndexOutOfBoundsException();
Node<E> node =null;
for(int i=size();i>index;i--){
//将栈顶删除
node = get(i);
node.prev = node;
theSize--;
}
return node.e;
}
@Override
public Iterator<E> iterator() {
return new MyStackLinkedIterator();
}
private class MyStackLinkedIterator<E> implements Iterator<E>{
private Node<E> node = (Node<E>) top.prev;
private boolean okRemove = false;
@Override
public boolean hasNext() {
return node!=null;
}
//
@Override
public E next() {
if(!hasNext())
throw new NoSuchElementException();
E e = (E) node.e;
node = node.prev;
okRemove = true;
return e;
}
@Override
public void remove() {
if(!okRemove)
throw new IllegalStateException();
MyStackLinked.this.top();
okRemove=false;
}
}
}
好了,大概就是这种实现形式。
备注1 :至于这里为什么要实现了 Iterable 接口,那个在上一篇帖子有说明