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

来源:互联网 发布:怎么在淘宝上买东西 编辑:程序博客网 时间:2024/05/22 18:55

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

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

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

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

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

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


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

    首先我们来看看顺序栈


顺序栈ArrayStack

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

package ArrayStack;import java.util.Arrays;/** * Created by jiangxs on 17-5-24. */public class ArrayStack<T> {    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<size;i++)            elements[i] = null;        size = 0;    }    public String toString(){        if (isEmpty())            return "[]";        else {            StringBuilder sb = new StringBuilder("[");            for (int i = size-1;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<String> ll = new ArrayStack<String>();        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当前栈中元素个数为: 4Process finished with exit code 0

    下面我们再来看看链栈:

    链栈的入栈操作如下图:


    链栈的出栈如下图:


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

链栈LinkStack

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

package LinkListStack;/** * Created by jiangxs on 17-5-24. */public class LinkListStack<T> {    //定义一个内部类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<String> ll = new LinkListStack<String>();        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当前栈中元素个数为: 4Process finished with exit code 0

参考:《大话数据结构》

原创粉丝点击