大话数据结构(五)——栈的两种java实现方式

    在我们生活当中经常会看到这样一种操作,比如我们往一个空羽毛球盒子里面放羽毛球(个人比较喜欢羽毛球,嘿嘿),放完后再将羽毛球一个一个取出的时候会发现,最先放进去的羽毛球往往最后才取出来,相反,最后放入的羽毛球往往最先取出。这个例子形象的说明了栈的操作方式,下面我们来看看什么是栈,以及栈的一些操作。

    那么什么是栈呢?栈就是限定在表尾进行插入和删除操作的线性表。我们将允许插入和删除的一端称为栈顶(top),而另一端就称之为栈底(bottom),当栈中无任何数据元素时称作空栈。由上面的例子可以知道羽毛球的放入和取出为后进先出的,那么栈与之相同,也是后进先出的(LIFO)结构。

    栈是一个线性表,它具有线性关系,即前驱后继的关系。由于栈限定了线性表插入和删除的位置,所以栈底也是固定的。在线性表中表头是栈底,表我是栈顶。最先入栈的只能在栈底。下面我们来看看栈的两种操作——进栈和出栈:

    进栈(push):栈的插入操作,也可称为压栈或者入栈,操作过程就类似上述的放羽毛球的过程。

    出栈(pop):栈的删除操作,也可称为弹栈,操作过程就类似上述的取羽毛球的过程。

    我们可以看看图片理解理解:

大话数据结构(五)——栈的两种java实现方式_第1张图片

    上面也说到了栈是一种线性表,而线性表有顺序存储结构和链式存储结构,所以栈的实现方式也有两种,即顺序栈和链式栈。

    首先我们来看看顺序栈

大话数据结构(五)——栈的两种java实现方式_第2张图片

顺序栈ArrayStack

其中栈顶为数组尾,类中包含入栈,出栈,清空等操作

package ArrayStack;

import java.util.Arrays;

/**
 * Created by jiangxs on 17-5-24.
 */
public class ArrayStack {
    private final int DEFAULT_SIZE = 10;//设置默认尺寸
    private int capacity;//保存当前数组长度
    private int addCapacity;//设置当超出原数组长度时增加的长度
    private Object[] elements;//初始化顺序栈数组
    private int size;//保存顺序栈中元素的个数

    //创建默认长度的空顺序栈
    public ArrayStack(){
        capacity = DEFAULT_SIZE;
        elements = new Object[capacity];
    }

    //创建指定长度的空顺序栈
    public ArrayStack(int capacity){
        this.capacity = capacity;
        elements = new Object[capacity];
    }

    /**
     * 创建指定长度的空顺序栈,并指定超出数组范围后的增量
     * @param capacity 设置指定长度
     * @param addCapacity 设置增量
     */
    public ArrayStack(int capacity,int addCapacity){
        this.capacity = capacity;
        this.addCapacity = addCapacity;
        elements = new Object[capacity];
    }

    //获取顺序栈的长度
    public int getSize(){
        return size;
    }

    //判断顺序栈是否为空栈
    public boolean isEmpty(){
        return size == 0;
    }

    //确保数组长度,如果超出就进行拓展
    private void ensureCapacity(int inputCapacity){
        //如果输入的数组长度大于原有数组的长度
        if (inputCapacity > capacity) {
            //若果有设定数组增量
            if (addCapacity > 0)
                while (inputCapacity > capacity)
                    //按照增量扩容,直到大于所需的数组容量
                    capacity += inputCapacity;
                //如果未设定数组增量
            else
                while (inputCapacity > capacity)
                    //将capacity左移,使其为大于所需容量
                    capacity <<= 1;
            //扩容后,将原数组复制到新数组中
            elements = Arrays.copyOf(elements, capacity);
        }
    }

    //进栈
    public void push(T element){
        //确保数组长度
        ensureCapacity(size+1);
        //元素进栈
        elements[size++] = element;
    }

    //出栈
    //同时返回弹出的元素
    public T pop(){
        //如果是空栈
        if (isEmpty())
            return null;
        T element = (T) elements[size-1];
        //释放栈顶元素并将长度减一
        elements[--size] = null;
        return element;
    }

    //获取栈顶元素
    public T getTop(){
        return (T)elements[size-1];
    }

    //清空顺序栈
    public void clear(){
        for (int i = 0;i= 0;i--)
                sb.append(elements[i].toString()+" ");
            sb.append("]");
            int len = sb.length();
            return sb.delete(len-2,len-1).toString();
        }
    }
}

测试代码:

package ArrayStack;

/**
 * Created by jiangxs on 17-5-24.
 */
public class ArrayStackTest {
    public static void main(String[] args) {
        ArrayStack ll = new ArrayStack();
        System.out.println("原栈中的元素: "+ll);
        System.out.println("----------进栈啦----------");
        //压栈
        ll.push("haha");
        ll.push("hehe");
        ll.push("xixi");
        ll.push("hiahia");
        ll.push("heihei");
        System.out.println("压栈后栈中所含元素: "+ll);
        //获取栈顶元素
        System.out.println("栈顶元素为: "+ll.getTop());
        //获取栈中元素个数
        System.out.println("当前栈中元素个数为: "+ll.getSize());
        //出栈
        System.out.println("----------出栈啦----------");
        ll.pop();
        System.out.println("出栈后栈中所含元素: "+ll);
        //获取栈顶元素
        System.out.println("栈顶元素为: "+ll.getTop());
        //获取栈中元素个数
        System.out.println("当前栈中元素个数为: "+ll.getSize());
    }
}

测试结果:

原栈中的元素: []
----------进栈啦----------
压栈后栈中所含元素: [heihei hiahia xixi hehe haha]
栈顶元素为: heihei
当前栈中元素个数为: 5
----------出栈啦----------
出栈后栈中所含元素: [hiahia xixi hehe haha]
栈顶元素为: hiahia
当前栈中元素个数为: 4

Process finished with exit code 0

    下面我们再来看看链栈:

    链栈的入栈操作如下图:

大话数据结构(五)——栈的两种java实现方式_第3张图片

    链栈的出栈如下图:

大话数据结构(五)——栈的两种java实现方式_第4张图片

下面我们来看看链栈的代码实现

链栈LinkStack

其中栈顶为结点top,类中包含入栈,出栈,清空等操作

package LinkListStack;

/**
 * Created by jiangxs on 17-5-24.
 */
public class LinkListStack {

    //定义一个内部类Node代表单链表的结点
    private class Node{
        private T element;
        private Node next;

        //初始化空构造器
        public Node(){}

        //初始化含参数构造器
        public Node(T element,Node next){
            this.element = element;
            this.next = next;
        }
    }

    private Node top;//存放栈顶结点
    private int size;//存放栈中结点数

    //初始化空栈
    public LinkListStack(){}

    //获取栈长度
    public int getSize(){
        return size;
    }

    //判断栈是否为空栈
    public boolean isEmpty(){
        return size == 0;
    }

    //进栈
    public void push(T element){
        //进栈时,新结点的后驱指针next指向旧top
        Node newNode = new Node(element,top);
        //进来的新结点更新为top
        top = newNode;
        size++;
    }

    //出栈
    //返回弹出的元素
    public T pop(){
        //如果弹出时栈为空则返回空
        if (isEmpty())
            return null;
        //用一个结点保存原头结点
        Node p = top;
        //将现在的头结点更新为原结点的下一个结点
        top = top.next;
        //将原头结点释放
        p.next = null;
        size--;
        return p.element;
    }

    //获取栈顶元素
    public T getTop(){
        //如果为空栈则返回空
        if (isEmpty())
            return null;
        return top.element;
    }

    //清空栈
    public void clear(){
        top = null;
        size = 0;
    }

    public String toString(){
        if (isEmpty())
            return "[]";
        else {
            StringBuilder sb = new StringBuilder("[");
            for (Node current = top;current != null;current = current.next)
                sb.append(current.element.toString()+"->");
            sb.append("]");
            int len = sb.length();
            return sb.delete(len-3,len-1).toString();
        }
    }
}

测试代码:

package LinkListStack;

/**
 * Created by jiangxs on 17-5-24.
 */
public class LinkListStackTest {
    public static void main(String[] args) {
        LinkListStack ll = new LinkListStack();
        System.out.println("原栈中的元素: "+ll);
        System.out.println("----------进栈啦----------");
        //压栈
        ll.push("haha");
        ll.push("hehe");
        ll.push("xixi");
        ll.push("hiahia");
        ll.push("heihei");
        System.out.println("压栈后栈中所含元素: "+ll);
        //获取栈顶元素
        System.out.println("栈顶元素为: "+ll.getTop());
        //获取栈中元素个数
        System.out.println("当前栈中元素个数为: "+ll.getSize());
        //出栈
        System.out.println("----------出栈啦----------");
        ll.pop();
        System.out.println("出栈后栈中所含元素: "+ll);
        //获取栈顶元素
        System.out.println("栈顶元素为: "+ll.getTop());
        //获取栈中元素个数
        System.out.println("当前栈中元素个数为: "+ll.getSize());
    }
}

测试结果:

原栈中的元素: []
----------进栈啦----------
压栈后栈中所含元素: [heihei->hiahia->xixi->hehe->haha]
栈顶元素为: heihei
当前栈中元素个数为: 5
----------出栈啦----------
出栈后栈中所含元素: [hiahia->xixi->hehe->haha]
栈顶元素为: hiahia
当前栈中元素个数为: 4

Process finished with exit code 0

参考:《大话数据结构》

你可能感兴趣的:(数据结构与算法)