java 队列与栈实现(链表与数组)

来源:互联网 发布:中国网络创始人 编辑:程序博客网 时间:2024/05/29 13:20

我们经常会问到java数据结构可以怎么实现,看过了算法之后得到很大启发,这里整理如下。

队列是一种先进先出(FIFO)的集合模型,而栈则是后进先出(LIFO)的集合模型,我们经常使用它们用来保存元素的相对顺序。Java中在java.util.LinkedList类中实现了关于队列和栈的实现,但是这是一个宽接口的例子,这里我们自己实现它以研究它的思路。

有两种基础可以用来实现:数组和链表

我们实现栈的基本要素如下:

int N 代表栈的容量

boolean isEmpty()用来判断栈是否为空

int size()返回栈的容量

void push()进栈操作,每次栈顶新增元素

T pop()出栈操作,由于出栈后栈中元素会得到释放,因此我们需要一个返回值纪录出栈元素以便操作。这里返回值为一个范型,可以把范型理解为占位符,即开始时不规定类型是什么,到后来用到时再定义,这里范型可以为任何类。

数组实现:

由于数组在初始化时必须设置存储容量,而我们并不知道我们的栈与队列需要多大的存储空间,因此我们对思路是在对元素进行进入操作时与容量大小进行比较,关键思路是如果超过了则对容量进行“扩容”,即复制一份数组并将原来那份废弃。在这里对元素使用率进行了判断,使其不回低于1/4.

public class StackInArray<T> implements Iterable<T> {private T[] a = (T[]) new Object[1];private int N = 0;public boolean isEmpty() {return N == 0;}public int size() {return N;}private void resize(int max) {T[] temp = (T[]) new Object[max];for (int i = 0; i < N; i++) {temp[i] = a[i];}a = temp;}public void push(T t) {if (N == a.length)resize(a.length << 1);//移位操作,相当于*2,感觉更能理解扩容一倍的意思。a[N++] = t;}public T pop() {T t = a[--N];a[N] = null;if (N > 0 && N == a.length / 4)resize(a.length >> 1);return t;}@Overridepublic Iterator<T> iterator() {return new ArrayIterator();}private class ArrayIterator implements Iterator<T> {private int i = N;@Overridepublic boolean hasNext() {return i > 0;}@Overridepublic T next() {return a[--i];}}}

这里栈的基本元素为一个范型数组。这里新增了一个void resize(int max)方法用来对数组进行大小调整。

当我们进栈和出栈时,实际上是对数组中最后一个标记

看完了数组实现的栈我们接下来看由链表实现的栈,首先复习一下链表。

链表定义如下:链表时一种递归的数据结构,它或者为空,或者是指向一个结点的引用,该结点含有一个范型的元素和一个指向另一条链表的引用。

在java中,我们可以用一个嵌套类定义结点实现链表

private class Node {T t;Node next;}

用链表实现的栈基本操作与用数组实现栈的操作一致,只不过我们这里用Node数据类型替代数组,因此在初始化的时候不需要定义栈的大小。


public class StackInChain<T> implements Iterable<T> {private Node first;// 栈顶private int N;// 容量private class Node {T t;Node next;}public boolean isEmpty() {return first == null;}public int size() {return N;}public void push(T t) {Node oldFirst = first;first = new Node();first.t = t;first.next = oldFirst;N++;}public T pop(){T t=first.t;first=first.next;N--;return t;}}

链表实现的栈思路很明显,每当push时就在头节点前新增一个节点,使其作为新的头节点,并使容量自增即可。出栈时将头节点向后移一位即可。


数据结构优点缺点数组通过索引可以直接访问任意元素在初始化时就需要知道元素的数量链表使用的空间大小与元素数量正比需要通过索引访问任意元素

0 0
原创粉丝点击