Java中的栈实现方法

本篇内容主要讲解“Java中的栈实现方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java中的栈实现方法”吧!

创新互联从2013年开始,是专业互联网技术服务公司,拥有项目成都网站设计、成都网站建设网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元东阿做网站,已为上家服务,为东阿各地企业和个人服务,联系电话:028-86922220

栈的实现

栈是一种先进后出的数据结构, 首先定义了栈需要实现的接口:

public interface MyStack {      /**       * 判断栈是否为空       */     boolean isEmpty();      /**       * 清空栈       */     void clear();      /**       * 栈的长度       */     int length();      /**       * 数据入栈       */     boolean push(T data);      /**       * 数据出栈       */     T pop();  }

栈的数组实现,底层使用数组:

public class MyArrayStack implements MyStack {      private Object[] objs = new Object[16];      private int size = 0;       @Override     public boolean isEmpty() {          return size == 0;      }       @Override     public void clear() {          // 将数组中的数据置为null, 方便GC进行回收          for (int i = 0; i < size; i++) {              objs[size] = null;          }          size = 0;      }       @Override     public int length() {          return size;      }       @Override     public boolean push(T data) {          // 判断是否需要进行数组扩容          if (size >= objs.length) {              resize();          }          objs[size++] = data;          return true;      }       /**       * 数组扩容       */     private void resize() {          Object[] temp = new Object[objs.length * 3 / 2 + 1];          for (int i = 0; i < size; i++) {              temp[i] = objs[i];              objs[i] = null;          }          objs = temp;      }       @SuppressWarnings("unchecked")      @Override     public T pop() {          if (size == 0) {              return null;          }          return (T) objs[--size];      }       @Override     public String toString() {          StringBuilder sb = new StringBuilder();          sb.append("MyArrayStack: [");          for (int i = 0; i < size; i++) {              sb.append(objs[i].toString());              if (i != size - 1) {                  sb.append(", ");              }          }          sb.append("]");          return sb.toString();      }  }  

栈的链表实现,底层使用链表:

public class MyLinkedStack implements MyStack {      /**       * 栈顶指针       */     private Node top;      /**       * 栈的长度       */     private int size;            public MyLinkedStack() {          top = null;          size = 0;      }            @Override     public boolean isEmpty() {          return size == 0;      }            @Override     public void clear() {          top = null;          size = 0;      }            @Override     public int length() {          return size;      }            @Override     public boolean push(T data) {          Node node = new Node();          node.data = data;          node.pre = top;          // 改变栈顶指针          top = node;          size++;          return true;      }            @Override     public T pop() {          if (top != null) {              Node node = top;              // 改变栈顶指针              top = top.pre;              size--;              return node.data;          }          return null;      }            /**       * 将数据封装成结点       */     private final class Node {          private Node pre;          private T data;      }  }

两种实现的比较,主要比较数据入栈和出栈的速度:

@Test public void testSpeed() {      MyStack stack = new MyArrayStack();      int num = 10000000;      long start = System.currentTimeMillis();      for (int i = 0; i < num; i++) {          stack.push(new Person("xing", 25));      }      long temp = System.currentTimeMillis();      System.out.println("push time: " + (temp - start));      while (stack.pop() != null)          ;      System.out.println("pop time: " + (System.currentTimeMillis() - temp));  }

MyArrayStack中入栈和出栈10,000,000条数据的时间:

push time:936

pop time:47

将MyArrayStack改为MyLinkedStack后入栈和出栈的时间:

push time:936

pop time:126

可见两者的入栈速度差不多,出栈速度MyArrayStack则有明显的优势。

为什么测试结果是这样的?可能有些朋友的想法是数组实现的栈应该具有更快的遍历速度,但增删速度应该比不上链表实现的栈才对。但是栈中数据的增删具有特殊性:只在栈顶入栈和出栈。也就是说数组实现的栈在增加和删除元素时并不需要移动大量的元素,只是在数组扩容时需要进行复制。而链表实现的栈入栈和出栈时都需要将数据包装成Node或者从Node中取出数据,还需要维护栈顶指针和前驱指针。

栈的应用举例

1. 将10进制正整数num转换为n进制

private String conversion(int num, int n) {      MyStack myStack = new MyArrayStack();      Integer result = num;      while (true) {          // 将余数入栈          myStack.push(result % n);          result = result / n;          if (result == 0) {              break;          }      }      StringBuilder sb = new StringBuilder();      // 按出栈的顺序倒序排列即可      while ((result = myStack.pop()) != null) {          sb.append(result);      }      return sb.toString();  }

2. 检验符号是否匹配. '['和']', '('和')'成对出现时字符串合法. 例如"[][]()", "[[([]([])()[])]]"是合法的; "([(])", "[())"是不合法的。

遍历字符串的每一个char, 将char与栈顶元素比较. 如果char和栈顶元素配对, 则char不入栈, 否则将char入栈. 当遍历完成时栈为空说明字符串是合法的。

public boolean isMatch(String str) {      MyStack myStack = new MyArrayStack();      char[] arr = str.toCharArray();      for (char c : arr) {          Character temp = myStack.pop();          // 栈为空时只将c入栈          if (temp == null) {              myStack.push(c);          }          // 配对时c不入栈          else if (temp == '[' && c == ']') {          }           // 配对时c不入栈          else if (temp == '(' && c == ')') {          }           // 不配对时c入栈          else {              myStack.push(temp);              myStack.push(c);          }      }      return myStack.isEmpty();  }

3. 行编辑: 输入行中字符'#'表示退格, '@'表示之前的输入全都无效。

使用栈保存输入的字符, 如果遇到'#'就将栈顶出栈, 如果遇到@就清空栈. 输入完成时将栈中所有字符出栈后反转就是输入的结果:

private String lineEdit(String input) {      MyStack myStack = new MyArrayStack();      char[] arr = input.toCharArray();      for (char c : arr) {          if (c == '#') {              myStack.pop();          } else if (c == '@') {              myStack.clear();          } else {              myStack.push(c);          }      }            StringBuilder sb = new StringBuilder();      Character temp = null;      while ((temp = myStack.pop()) != null) {          sb.append(temp);      }      // 反转字符串      sb.reverse();      return sb.toString();  }

到此,相信大家对“Java中的栈实现方法”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!


文章题目:Java中的栈实现方法
本文地址:http://azwzsj.com/article/jsioho.html