大话数据结构(五)——栈的两种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
参考:《大话数据结构》
- 大话数据结构(五)——栈的两种java实现方式
- 大话数据结构(六)——队列的两种java实现方式
- 大话数据结构(二)——线性表链式存储结构(单链表)的java实现
- 大话数据结构(三)——单向循环链表的java实现
- 大话数据结构(四)——双向链表的java实现
- 大话数据结构(一)——线性表顺序存储结构的java实现
- 数据结构学习之栈的两种实现方式
- Java栈的两种实现方式
- java多线程—常用的两种实现多线程方式
- 《大话数据结构》读书笔记(五)
- 大话数据结构(五)串
- 数据结构与算法Java版——树的两种表现方式
- 大话数据结构(七)——二叉树创建与遍历(递归、非递归)的java实现
- Java多线程(一)——实现多线程的两种方式
- Java实现多线程的两种方式
- Java定时器 实现的两种方式
- Java定时器 实现的两种方式
- Java实现多线程的两种方式
- POJ
- 分享一个gif截图工具
- ajax的data偶然数据溢出。。。
- 循环双向链表
- 网络异常模拟测试方法
- 大话数据结构(五)——栈的两种java实现方式
- MYSQL的用户变量(@)和系统变量(@@)
- Unity导入STL格式模型(一)
- C Primer Plus 第10章 数组和指针 编程练习
- 程序崩溃时自动记录minidump的c++类
- PYTHON PYTESSER 的安装
- 《摔跤吧!爸爸》中引人深思的中英文台词
- [译] ConstraintLayout基础之Chains链
- highcharts