二.Java栈与队列的实现:

来源:互联网 发布:网络犯罪调查 编辑:程序博客网 时间:2024/06/14 15:13

栈和队列是两种相像的经典的数据类型,都是对数据添加删除做限制的线性表。其不同之处就在于出栈(pop)和出列(dequeue)的方式。栈是先进后出,队列是先进先出。

<1>Java虽说没有所谓的指针,但其实对于每个对象的引用就是指针,所以,栈可以用链表来实现:

public class Stack {    Node first = null;    private class Node {//定义内部类,实现节点的数据类型        String value;        Node next;    }    public boolean isEmpty() {//判空函数        return first == null;    }    public void push(String item) {//入栈        Node oldfirst = first;        first = new Node();        first.value = item;        first.next = oldfirst;    }    public String pop() {//出栈        String item = first.value;        first = first.next;        return item;    }    public static void main(String[] args) {        Stack zhan = new Stack();        System.out.println(zhan.isEmpty());        zhan.push("hello");        zhan.push("world!");        System.out.println(zhan.pop());    }}

当然,栈也可以用简单数组实现:

public class Stack {    String S[];    int n = 0;//代表了栈顶    public Stack(int capacity) {//要求客户端定义栈大小        S = new String[capacity];    }    public boolean isEmpty() {//判空函数        return n == 0;    }    public void push(String item) {//入栈        S[n++] = item;    }    public String pop() {//出栈        String item = S[--n];        S[n] = null;//这两行代码是细节,如果直接返回S[--n]数组中对对象的引用还存在,可能会造成内存浪费。        return item;    }    public static void main(String[] args) {        Stack zhan = new Stack(2);        System.out.println(zhan.isEmpty());        zhan.push("hello");        zhan.push("world!");        System.out.println(zhan.pop());    }}

数组实现栈确实方便简单,但是它却必须规定大小,而在实际应用中我们的客户端往往不知道究竟需要多大的栈,所以我们可以对程序进行改进,动态改变数组大小:

public class Stack {    String S[] = new String[1];    int n = 0;    public boolean isEmpty() //判空函数    {        return n == 0;    }    public void push(String item) //入栈    {        S[n++] = item;        if( n == S.length )            resize(2*S.length);     }    public String pop() //出栈    {        String item = S[--n];        S[n] = null;        if( n == S.length/4)//如果判断是否等于S.length/2可能会出现“抖动”现象            resize(S.length/2);        return item;    }    private void resize(int capacity)//重规定数组大小    {        String copy[] = new String[capacity];        for( int i = 0; i<n; i++ )            copy[i] = S[i];        S = copy;    }    public static void main(String[] args) {        Stack zhan = new Stack();        System.out.println(zhan.isEmpty());        zhan.push("hello");        zhan.push("world!");        System.out.println(zhan.pop());    }}

这样就解决了数组实现栈大小限定的弊端。

对于两种不同的实现,我们应当发现,数组的基本操作要比链表更快,这就使得在处理数据时整体上是数组实现的栈效率更高。不过当数组进行动态伸缩的时候,操作时间会明显变长。所以可以根据实际需求选择实现方法。

<2>对于队列的实现,基本上和栈类似,但是链表实现我们要维护两个节点:first和last,enqueue时从last节点入队,dequeue时从first节点出队:

public class Queue {    private Node first, last;    private class Node{        String value;        Node next;    }    public boolean isEmpty()//判空函数    {        return first == null;    }    public void enqueue(String value)//从last节点入队    {        Node oldlast = last;        last = new Node();        last.value = value;        last.next = null;        if(isEmpty())            first = last;        else            oldlast.next = last;    }    public String dequeue()//从first节点出队    {        String item = first.value;        first = first.next;        return item;    }    public static void main(String[] args) {        Queue duilie = new Queue();        System.out.println(duilie.isEmpty());        duilie.enqueue("hello");        duilie.enqueue("world!");        System.out.println(duilie.dequeue());    }}

以下是数组实现:

public class Queue {    private int first, last;    String S[] = new String[1];    public boolean isEmpty()//判空函数    {        return first == last;    }    public void enqueue(String value)//入队    {        S[last++] = value;        if( last == S.length )            resize(2*S.length);    }    public String dequeue()//出队    {        String item = S[first];        S[first++] = null;        if( last == S.length/4 )            resize(S.length/2);        return item;    }    private void resize(int size)//此处重定义数组比栈稍微复杂,需要找到first节点,将其重新归零     {        String copy[] = new String[size];        int j = 0;        while( S[j] == null)            j++;            for( int i = 0; i<last; i++ )            copy[i] = S[i+j];        S = copy;    }    public static void main(String[] args) {        Queue duilie = new Queue();        System.out.println(duilie.isEmpty());        duilie.enqueue("hello");        duilie.enqueue("world!");        System.out.println(duilie.dequeue());    }}

数组实现多了一些栈不需要考虑的因素,关于两种实现方法的性能分析同栈。

(关于背包的实现,就是一个不可以取出的栈,除掉pop方法即可。)