二.Java栈与队列的实现:

本文探讨了栈和队列这两种数据类型的实现方式。在Java中,栈可以通过链表或固定大小数组实现,动态调整数组大小可以解决大小限定问题。数组实现的栈在一般情况下效率更高,但动态伸缩时速度减慢。队列的实现同样可以采用链表或数组,链表需要维护first和last节点,而数组实现则较复杂。背包的实现类似栈,但不允许出队操作。
摘要由CSDN通过智能技术生成

栈和队列是两种相像的经典的数据类型,都是对数据添加删除做限制的线性表。其不同之处就在于出栈(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方法即可。)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值