Java中栈的创建与其常见的应用场景

Posted RS_mine

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中栈的创建与其常见的应用场景相关的知识,希望对你有一定的参考价值。

在Java开发中,使用Deque接口的实现类来创建栈是最常用和主流的方式之一。Deque接口根据其名字可知,Deque : double-end queue(双端队列)。众所周知,根据不同的设计方式,队列可以形成栈,栈也可组成队列,故在Deque接口中提供了用来操作队列和栈的方法,并且在其子类中进行了实现。最常用的两个实现类分别是ArrayDeque和LinkedList,第一个表示是使用数组来进行实现的双端队列,可以在两端进行元素的添加和删除操作,并且在数据量比较大的时候仍可以高效的工作。而第二个LinkedList的底层是使用双向链表来实现的,与ArrayDeque相比,它的性能略低,但是它在元素的插入和删除操作方面比较灵活。

(1)Java中栈的创建方式

  ① 使用Stack类

  Java提供了最容易根据名字想起的Stack类,这也是在Java 6以及更早版本常用的方式。

Stack<String> stack = new Stack<>(); // 创建一个栈,泛型为String,一般来讲String作为泛型是很安全的
stack.push("AAAI");
stack.push("KDD");
stack.push("SIGIR");
stack.push("WSDM");
System.out.println(stack.pop()); // 输出"WSDM",并将其从栈中移除,表明后进先出
System.out.println(stack.peek()); // 输出"SIGIR",不移除栈顶元素"SIGIR",只查看,也体现后进先出

  以下是Stack类中的一类常用方法:

public class Stack<E> extends Vector<E> 
  
    public Stack()  // 构造方法
    

    public E push(E item)  // 往栈中添加元素
        addElement(item);

        return item;
    

    public synchronized E pop()  // 移除栈顶元素, 该方法是线程安全的
        E       obj;
        int     len = size();

        obj = peek();
        removeElementAt(len - 1);

        return obj;
    

    public synchronized E peek()  // 查看栈顶元素,该方法是线程安全的
        int     len = size();

        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    
    public boolean empty()  // 判断栈空
        return size() == 0;
    

  ②使用Deque接口的实现类来创建栈(推荐使用)

  在Java开发中,使用Deque接口的实现类来创建栈是最常用和主流的方式之一。Deque接口根据其名字可知,Deque : double-end queue(双端队列)。众所周知,根据不同的设计方式,队列可以形成栈,栈也可组成队列,故在Deque接口中提供了用来操作队列和栈的方法,并且在其子类中进行了实现。最常用的两个实现类分别是ArrayDeque和LinkedList,第一个表示是使用数组来进行实现的双端队列,可以在两端进行元素的添加和删除操作,并且在数据量比较大的时候仍可以高效的工作。而第二个LinkedList的底层是使用双向链表来实现的,与ArrayDeque相比,它的性能略低,但是它在元素的插入和删除操作方面比较灵活。

  这两种的部分用法如下所示:

ArrayDeque(栈)实现类的简单使用:
public void testArrayQue() Deque<String> arrQue = new ArrayDeque<>(); arrQue.push("济公"); arrQue.push("李文龙"); arrQue.push("钱掌柜"); arrQue.push("王掌柜"); arrQue.push("李管家"); String pop = arrQue.pop(); System.out.println(pop); // 输出:李管家 String peek = arrQue.peek(); System.out.println(peek); // 输出:王掌柜 System.out.println(Arrays.toString(arrQue.toArray())); // 输出:[王掌柜, 钱掌柜, 李文龙, 济公]
LinkedList(栈)实现类的简单使用:
public void testLinkedList()
        Deque<Integer> linkedQue = new LinkedList<>();

        linkedQue.push(123);
        linkedQue.push(234);
        linkedQue.push(345);
        linkedQue.push(456);
        linkedQue.push(567);

        Integer pop = linkedQue.pop();
        System.out.println(pop); // 输出:567

        Integer peek = linkedQue.peek();
        System.out.println(peek); // 输出:456

        System.out.println(linkedQue); // 输出:[456, 345, 234, 123]

(2)栈常见的应用场景

  ① 浏览器的历史记录; ② 缓存的实现;③ activity的启动模式;④ CPU中栈的实现;⑤ word自动保存;⑥ 解析计算式;⑦ 解析xml或json;⑧ 函数调用;⑨ 表达式求值

Tarjan中栈的分析与SLT栈的实现

首先看一下手写的栈:

1 do{
2     printf("%d ",stack[index]);
3     visit[stack[index]]=0;
4     index--;
5     }while(x!=stack[index+1]);//出栈,并且输出。
6 printf("\n");

我们可以发现。x是与index的上一个元素比较的

 

举个例子

栈:1 3 2 4 5     x=2

这样的话会输出 5  4   2

 

但是stl不支持和栈顶的上一个元素比较,因为上一个元素一定是被pop掉的。

那么我们可以怎么实现呢?

 

1.首先我们需要明白一点,如果我们把循环的条件改为

 1 x!=stack.top; 

 

那么当栈已经空的时候,还是会执行一下判断操作,这样就会导致re,

所以我们可以记录下pop之前的元素,这样就可以保证在判断的时候不会越界,而且是与pop之前的元素进行比较的

code:

 

1 int h;
2 do
3 {
4     h=s.top();
5     if(!color[s.top()])
6     color[s.top()]=colornum;
7     vis[s.top()]=0;
8     s.pop();
9 }while(now!=h);

 

 

 

 

2.一般的do while语句都可以用while语句来实现

我们如果单纯的把do while改成while,

那么在上面的例子中会输出 5  4

所以我们还需要判断一次,把当前的栈顶给输出

代码:

 1 while(now!=s.top())
 2 {
 3     if(!color[s.top()])
 4     color[s.top()]=colornum;
 5     vis[s.top()]=0;
 6     s.pop();
 7 }
 8 if(!color[s.top()])
 9 color[s.top()]=colornum;
10 vis[s.top()]=0;
11 s.pop();

 

如果你还有其他什么写法的话欢迎发表评论或者通过其他方式联系我。

谢谢

 

以上是关于Java中栈的创建与其常见的应用场景的主要内容,如果未能解决你的问题,请参考以下文章

Java中栈的使用

python中栈的实现

Java中栈的两种实现

1289大鱼吃小鱼(STL中栈的应用)

详解数据结构中栈的定义和操作

Tarjan中栈的分析与SLT栈的实现