数据结构|栈

完成阅读您将会了解栈的:

  1. 概念
  2. 构建方法
  3. 基本操作
  4. C++实现
  5. Rust实现

1. 概念

Stack)是一种抽象数据类型,遵循后进先出Last-In-First-Out, LIFO)原则,单端开放的线性表,如图1[1]。栈可以模拟递归Recursion),回溯Backtracking),也常用来辅助完成深度优先搜索Depth First Search)算法的实现。

图1:栈结构

![图1:栈结构

2. 构建方法

数组单链表都可以作为构建栈的基础容器。关于链表的内容请参见数据结构链表中的介绍。

3. 基本操作

操作 描述 时间复杂度 空间复杂度
PUSH(value) 栈头入栈 \(\Theta(1)\) \(\Theta(1)\)
POP() 栈头出栈 \(\Theta(1)\) \(\Theta(1)\)

栈的入栈出栈过程分别如图2-3[2]所示。

图2:入栈过程

图2:入栈过程

图3:出栈过程

图3:出栈过程

4. C++实现

template <class T> struct Node {
  T val;
  Node *next;
  Node(auto val, auto next) : val(val), next(next) {}
};

template <class T> class Stack {
  Node<T> *head;
  size_t len;

public:
  Stack() : head(nullptr), len(0) {}
  ~Stack() {
    while (head) {
      auto garbage = head;
      head = head->next;
      delete garbage;
    }
  }
  constexpr auto top() const { return head->val; }
  inline void pop() noexcept {
    if (head) {
      auto garbage = head;
      head = head->next;      
      delete garbage;
      --len;
    }
  }
  inline void push(auto val) noexcept {
    head = new Node<T>(val, head);
    ++len;
  }
  constexpr auto empty() const noexcept { return len == 0; }
  constexpr auto size() const noexcept { return len; }
};

此外,C++标准库提供了栈stack直接使用。

5. Rust实现

impl<T> Stack<T> {
    #[inline]
    pub fn new() -> Self { Self { head: None, size: 0 } }
    #[inline]
    pub fn push(&mut self, val: T) {
        self.head = Some(Box::new(Node { next: self.head.take(), val }));
        self.size+=1;
    }
    #[inline]
    pub fn pop(&mut self) {
        if let Some(node) = self.head.take() {
            self.head = node.next;
            self.size-=1;
        }
    }
    #[inline]
    pub fn top(&self) -> Option<&T> {
        self.head.as_ref().map(|node| { &node.val })
    }
    #[inline]
    pub fn empty(&self) -> bool { self.size == 0 }
    #[inline]
    pub fn len(&self) -> usize { self.size }
}

impl<T> Drop for Stack<T> {
    fn drop(&mut self) {
        let mut iter = self.head.take();
        while let Some(mut node) = iter { iter = node.next.take(); }
    }
}

struct Stack<T> {
    head: Option<Box<Node<T>>>,
    size: usize,
}

struct Node<T> {
    val: T,
    next: Option<Box<Node<T>>>,
}

6. 自我测试

伪代码实践
N/A

LeetCode选荐

  1. Next Greater Element I
  2. Simplify Path
  3. Evaluate Reverse Polish Notation
  4. Next Greater Element II
  5. Maximum Frequency Stack

测试参考解答

让每一天足够精致,期待与您的再次相遇! ^_^


  1. 图片引自Wikipedia,在此鸣谢。 ↩︎

  2. 图片引自tutorialspoint,在此鸣谢。 ↩︎

posted @ 2021-07-06 19:33  我的名字被占用  阅读(90)  评论(0)    收藏  举报