看完了《算法(第四版)》中对栈这种数据结构的实现,记录一下。
实现栈的思路如下::
首先实现两个基本的属性,一个泛型数组用来储存栈元素,一个整型数据用来记录栈中的元素数量:
private Item[] a = (Item[]) new Object[1];
private int N = 0;
之后实现两个比较基本的成员方法,isEmpty用来判断栈是否为空,size用来返回栈中元素的个数:
public boolean isEmpty()
{
return N == 0;
}
public int size()
{
return N;
}
为了实现动态调节数组大小,添加一个reSize方法用来改变栈的容量:
private void reSize(int max)
{
Item[] temp = (Item[]) new Object[max];
for (int i = 0; i < N; i++)
{
temp[i] = a[i];
}
a = temp;
}
通过实现push和pop方法实现压栈和出栈的操作,在入栈时对栈的元素数量进行判断,如果栈满了,则自动扩充为原来两倍。出栈时,先要对出栈后的元素置空,避免对象游离,然后对栈中的元素数量进行判断,如果大于0且小于原容量的1/4,则将栈的容量减小为原先的一半,这样还可以留出比当前元素数量多一倍的空间进行使用,且不会造成空间浪费:
public void push(Item item)
{
if (N == a.length)
{
reSize(a.length * 2);
}
a[N++] = item;
}
public Item pop()
{
Item temp = a[--N];
a[N] = null;
if (N > 0 && N < a.length / 4)
{
reSize(a.length / 2);
}
return temp;
}
最后要实现迭代功能,首先要继承Iterable<Item>接口,这个接口需要我们实现一个Iterator方法,这个方法需要一个Iterator<Item>类型的返回值,在栈的实现中我们需要对数组进行逆向遍历,所以我们封装一个继承自Iterator<Item>的ReverseArrayIterator类,这是一个嵌套类,并且我们对其的remove置空,因为我们不想再迭代时候修改数据,最后让Iterator方法返回一个此类对象即可:
private class ReverseArrayIterator implements Iterator<Item>
{
private int i = N;
@Override
public boolean hasNext()
{
return i > 0;
}
@Override
public Item next()
{
return a[--i];
}
@Override
public void remove()
{
}
}
@Override
public Iterator<Item> iterator()
{
return new ReverseArrayIterator();
}
完整实现代码:
package Test;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
import java.util.Iterator;
public class ResizingArrayStack<Item> implements Iterable<Item>
{
private Item[] a = (Item[]) new Object[1];
private int N = 0;
public boolean isEmpty()
{
return N == 0;
}
public int size()
{
return N;
}
private void reSize(int max)
{
Item[] temp = (Item[]) new Object[max];
for (int i = 0; i < N; i++)
{
temp[i] = a[i];
}
a = temp;
}
public void push(Item item)
{
if (N == a.length)
{
reSize(a.length * 2);
}
a[N++] = item;
}
public Item pop()
{
Item temp = a[--N];
a[N] = null;
if (N > 0 && N < a.length / 4)
{
reSize(a.length / 2);
}
return temp;
}
private class ReverseArrayIterator implements Iterator<Item>
{
private int i = N;
@Override
public boolean hasNext()
{
return i > 0;
}
@Override
public Item next()
{
return a[--i];
}
@Override
public void remove()
{
}
}
@Override
public Iterator<Item> iterator()
{
return new ReverseArrayIterator();
}
public static void main(String args[])
{
ResizingArrayStack<String> s = new ResizingArrayStack<>();
while (!StdIn.isEmpty())
{
String item = StdIn.readString();
if (!item.equals("-"))
{
s.push(item);
} else if (!s.isEmpty())
{
StdOut.println(s.pop() + " ");
}
}
StdOut.println("("+s.size()+"left on stack)");
}
}