栈Stack |队列Queue| 双端队列Deque| 优先队列PriorityQueue

堆栈和队列特点:
1. Stack - First In Last Out(FILO) 先入后出,先进来的被压入栈底
    .Array or Linked List
2. Queue - First In First Out(FIFO) 排队时先来先出
    .Array or Doubly Linked List

1. Java中栈的实现API

在Java中,用Deque可以实现Stack的功能:

  • 把元素压栈:push(E)/addFirst(E)
  • 把栈顶的元素“弹出”:pop(E)/removeFirst()
  • 取栈顶元素但不弹出:peek(E)/peekFirst()

为什么Java的集合类没有单独的Stack接口呢?因为有个遗留类名字就叫Stack,出于兼容性考虑,所以没办法创建Stack接口,只能用Deque接口来“模拟”一个Stack了。不要使用遗留类Stack

当我们把Deque作为Stack使用时,注意只调用push()/pop()/peek()方法,不要调用addFirst()/removeFirst()/peekFirst()方法,这样代码更加清晰。

Stack,ArrayDeque,LinkedList都可以作为栈使用:

数据结构-04 |栈 |队列

    由继承树看出,三者都是Collection的间接实现类。        ArrayDeque实现Deque接口,Stack继承于Vector,LinkedList实现Deque与List接口。

区别

底层数据存储方式:


  存储方式
Stack 长度为10的数组
ArrayDeque 长度为16的数组
LinkedList

链表

 


线程安全

  线程安全
Stack 线程同步
ArrayDeque 线程不同步
LinkedList 线程不同步

使用Collections工具类中synchronizedXxx() 可以将线程不同步的ArrayDeque以及LinkedList转换成线程同步。

性能选项

      通常情况下,不推荐使用Vector以及其子类Stack (它们实现了线程同步的功能,所以性能比较差);

  频繁的插入、删除操作,未知的初始数据量:LinkedList ;

  频繁的随机访问操作:ArrayDeque

另一个区别是:LinkedList支持null元素,而ArrayDeque不支持。

2. Java中Queue队列的API

队列Queue实现了一个先进先出(FIFO)的数据结构:

  • 通过add()/offer()方法将元素添加到队尾;
  • 通过remove()/poll()从队首获取元素并删除;
  • 通过element()/peek()从队首获取元素但不删除。

要避免把null添加到队列。

// 这是一个List:  List<String> list = new LinkedList<>();
// 这是一个Queue: Queue<String> queue = new LinkedList<>();
LinkedList即实现了List接口,又实现了Queue接口,但是,在使用的时候,如果我们把它当作List,就获取List的引用,如果我们把它当作Queue,就获取Queue的引用
ArrayDeque也实现了Deque接口(Deque接口继承了Queue接口)

3. 双端队列Deque的API

  Deque是一个接口,它的实现类有ArrayDequeLinkedList  (LinkedList真是一个全能选手,它即是List,又是Queue,还是Deque

// 不推荐的写法: LinkedList<String> deque = new LinkedList<>();
// 推荐的写法:  Deque<String> deque = new LinkedList<>(); (面向抽象编程的一个原则就是:尽量持有接口,而不是具体的实现类。)

  • 将元素添加到队首: addFirst()即push() offerFirst();                   
  • 将元素添加到队尾:addLast()即add() offerLast() 即offer()   
  • 从队首获取元素并删除:removeFirst()即remove() pop() pollFirst() 即poll()  
  • 从队尾获取元素并删除:removeLast()pollLast()
  • 从队首获取元素但不删除:getFirst()peekFirst() 即peek()                 
  • 从队尾获取元素但不删除:getLast()peekLast()
  • 总是调用xxxFirst()/xxxLast()以便与Queue的方法区分开;
  • 避免把null添加到队列。

如果直接写deque.offer(),我们就需要思考,offer()实际上是offerLast(),我们明确地写上offerLast(),不需要思考就能一眼看出这是添加到队尾。

因此,使用Deque,推荐总是明确调用offerLast() /offerFirst()或者pollFirst() /pollLast()方法。

 数据结构-04 |栈 |队列

4. 优先队列PriorityQueue的API

Queue<String> q = new PriorityQueue<>(); 

PriorityQueueQueue的区别在于,它的出队顺序与元素的优先级有关,对PriorityQueue调用remove()poll()方法,返回的总是优先级最高的元素。

要使用PriorityQueue,我们就必须给每个元素定义“优先级”。

PriorityQueue实现了一个优先队列:从队首获取元素时,总是获取优先级最高的元素。

PriorityQueue默认按元素比较的顺序排序(必须实现Comparable接口),也可以通过Comparator自定义排序算法(元素就不必实现Comparable接口)。

放入PriorityQueue的元素,必须实现Comparable接口,PriorityQueue会根据元素的排序顺序决定出队的优先级。

如果我们要放入的元素并没有实现Comparable接口怎么办?PriorityQueue允许我们提供一个Comparator对象来判断两个元素的顺序。

 

1. 栈Stack 

 Stack中文名可叫堆栈,不能叫堆,堆是heap

手写栈堆比较少了,很多语言在标准库都实现了。

1.1 概念与特性 

    后进先出,先进后出,这就是典型的“栈”结构。  

    从栈的操作特性上来看,栈是一种“操作受限”的线性表,只允许在一端插入和删除数据从功能上来说,数组或链表可以替代栈,但特定的数据结构是对特定场景的抽象,而且,数组或链表暴露了太多的操作接口,操作上的确灵活自由,但使用时就比较不可控,自然也就更容易出错。

  当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,我们就应该首选“栈”这种数据结构

   最近相关性  《====》 栈    现实中的洋葱,一层层,反应在工程中都具有 从外而内 或者 由内而外这种逐渐扩散,且它的最外层和最外层是一对,最内层和最内层是一对 可叫最近相关性数据结构-04 |栈 |队列

 

栈:查询  O(n),平均情况,要看它栈中栈底的元素,要清空了才能看到。

       插入和删除它的栈顶元素只需要一次性操作,时间复杂度是O(1)。

1.2 如何实现一个“栈”?

            从栈的定义里,栈主要包含两个操作,入栈和出栈,即在栈顶插入一个数据和从栈顶删除一个数据

自定义一个栈既可以用数组来实现,也可以用链表来实现。 用数组实现的栈,叫作顺序栈,用链表实现的栈,叫作链式栈

// 基于数组实现的顺序栈
public class ArrayStack {
    private String[] items;  // 数组
    private int count;       // 栈中元素个数
    private int n;           // 栈的大小
    // 初始化数组,申请一个大小为 n 的数组空间
    public ArrayStack(int n) {
        this.items = new String[n];
        this.n = n;
        this.count = 0;
    }
    // 入栈操作
    public boolean push(String item) {
        // 数组空间不够了,直接返回 false,入栈失败。
        if (count == n) return false;
        // 将 item 放到下标为 count 的位置,并且 count 加一
        items[count] = item;
        ++count;
        return true;
    }
    // 出栈操作
    public String pop() {
        // 栈为空,则直接返回 null
        if (count == 0) return null;
        // 返回下标为 count-1 的数组元素,并且栈中元素个数 count 减一
        String tmp = items[count - 1];
        --count;
        return tmp;
    }
}
View Code

相关文章:

  • 2021-07-31
  • 2021-11-27
  • 2021-12-21
  • 2022-01-17
  • 2021-08-07
  • 2021-09-23
  • 2021-05-05
  • 2021-11-15
猜你喜欢
  • 2021-08-17
  • 2021-11-18
  • 2021-12-20
  • 2022-12-23
  • 2021-08-24
  • 2021-11-26
相关资源
相似解决方案