用集合模拟栈,队列的基本操作
栈和队列是我们接触的比较基本的数据结构,当时在学数据结构的时候,根本不懂这是什么,什么先进先出,先进后出,但是后来有一天突然就想明白了,可能对新的知识有个接触的过程。
在后来的为了更好的理解栈和队列的特点,决定用java模拟栈和队列
用什么来存储数据呢?数组很好,但是每次添加数据,数组的长度怎么设置,由于数组的长度是固定的,如果要扩容就需要重新创建一个数组把原来的数组中的数据复制过去.但是集合就不需要了,用List,那么用ArrayList还是LinkedList呢?其实他们两个都可以实现,但是他们两个底层用的存储结构是有太大的区别。ArrayList是长度可变数组,但是数组的长度是不能够改变的?通过源码我们可以看出,其实ArrayList的底层存储结构还是数组,通过他的add方法可以看到,其中复制数组用到了System类中的arraycopy方法,这个方法是复制数组比较快的方法,用native关键字修饰(用其他语言编写)
既然看到ArrayList底层也是用到数组,面对栈和队列,基本的操作是添加数据和删除数据,这个特点还是用LinkedList比较快,LinkedList底层用到的存储结构是链表,
我们依旧看他的add方法,他的add方法调用了另一个方法,在他的方法中我们可以看到创建节点,添加节点
具体的文档介绍可以参考http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
确定了存储结构那么就需要弄清楚栈和队列的存储结构
栈类似于一个桶,我们往里面放东西,想想里面的东西我们怎么放进去,一层压一层,先放的一定在下面,最后放的一定在最上面,我们只能一层一层的拿开,最后才能拿到最下面那个,也就是最先放的。
那么队列呢,他更像一个排队的队伍,队列中的数据好比队伍中的人,排队的人都是最先来的排在最前面,后来的排在最后面,这样最开始走的就是最先来的,
我们知道了两个结构的特点,既然可以利用List我们就要充分利用List的特点
栈:
package demo1; import java.util.LinkedList; import java.util.List; public class Stacks { private List<Object> list = new LinkedList<Object>(); private int i=0; public void inStacks(Object o) { list.add(o); i++; } public Object outStacks() { if (i != 0) { Object o = list.get(i-1); list.remove(list.get(i-1)); i--; return o; } return null; } public boolean empty() { return i == 0; } }队列:
package demo1; import java.util.LinkedList; import java.util.List; public class Queues { private List<Object> list = new LinkedList<Object>(); private int i=0; public void add(Object o) { list.add(o); i++; } public Object out() { if (i != 0) { Object o = list.get(0); list.remove(list.get(0)); i--; return o; } return null; } public boolean empty() { return i == 0; } }我们可以利用两个栈来实现队列的操作,先把所有元素入栈,之后挨个弹出放入另一个栈中,这样再弹出的时候就是按照放入顺序弹出的,要注意的是,先另一个栈中压入数据的时候,应确保元素全部转移过去,要放入元素的栈也应该确定空后在放入元素
其实java提供了栈Stack和队列Queue,要注意的是栈Stack是一个类,而队列Queue是一个接口,使用的时候要注意
通过看Queue的源码我们看到,Queue接口与List、Set同一级别,都是继承了Collection接口。LinkedList实现了Queue接 口。感觉好奇怪,我们又绕回来了……
栈和队列中具体的方法介绍可以参考:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
队列在应用中很广,我们在访问网站的时候,如果是网站能承受的同时访问的人数就那么多,但是人来了很多,先来的先访问,和买票一样。