C++ 数据结构:栈的原理与实践

一、栈的基本概念

栈(Stack)是一种遵循后进先出(LIFO)原则的线性数据结构。它就像一叠盘子,最后放入的盘子总是最先被取出。栈的核心操作包括:

  • 压栈(Push):向栈顶添加元素
  • 弹栈(Pop):移除栈顶元素
  • 查看栈顶(Top):获取栈顶元素但不删除
  • 判空(Empty):检查栈是否为空

二、栈的实现方式

1. 数组实现(静态栈)

使用数组存储元素,通过栈顶指针(top)管理栈状态:

template<typename T>
class ArrayStack {
private:
    T* data;
    int capacity;
    int top;

public:
    ArrayStack(int size = 10) : capacity(size), top(-1) {
        data = new T[capacity];
    }

    void push(const T& item) {
        if (top == capacity - 1) throw std::overflow_error("Stack is full");
        data[++top] = item;
    }

    T pop() {
        if (empty()) throw std::underflow_error("Stack is empty");
        return data[top--];
    }

    T top() const {
        if (empty()) throw std::underflow_error("Stack is empty");
        return data[top];
    }

    bool empty() const { return top == -1; }
    int size() const { return top + 1; }
};

2. 链表实现(动态栈)

通过链表节点动态管理内存:

template<typename T>
class ListNode {
public:
    T data;
    ListNode* next;
    ListNode(const T& val) : data(val), next(nullptr) {}
};

template<typename T>
class ListStack {
private:
    ListNode<T>* top;

public:
    ListStack() : top(nullptr) {}

    void push(const T& item) {
        ListNode<T>* newNode = new ListNode<T>(item);
        newNode->next = top;
        top = newNode;
    }

    T pop() {
        if (empty()) throw std::underflow_error("Stack is empty");
        T result = top->data;
        ListNode<T>* temp = top;
        top = top->next;
        delete temp;
        return result;
    }

    T top() const {
        if (empty()) throw std::underflow_error("Stack is empty");
        return top->data;
    }

    bool empty() const { return top == nullptr; }
    int size() const {
        int count = 0;
        ListNode<T>* current = top;
        while (current) {
            count++;
            current = current->next;
        }
        return count;
    }
};

三、标准库实现

C++ 标准库提供了stack容器适配器,默认基于deque实现:

#include <stack>
#include <iostream>

int main() {
    std::stack<int> st;
    st.push(10);
    st.push(20);
    std::cout << st.top() << std::endl; // 输出20
    st.pop();
    std::cout << st.size() << std::endl; // 输出1
    return 0;
}

四、典型应用场景

  1. 函数调用栈:记录函数调用层级
  2. 括号匹配:验证括号是否正确闭合
  3. 表达式求值:中缀表达式转后缀表达式
  4. 回溯算法:迷宫路径搜索、八皇后问题
  5. 浏览器前进后退:记录访问历史

五、实现方式对比

 

特性数组实现链表实现
内存分配静态分配动态分配
访问效率O(1)O(1)
空间利用可能浪费内存按需分配
扩展性需要预分配空间动态扩展
实现复杂度较低较高

六、性能优化建议

  1. 对于高频操作场景,优先选择数组实现
  2. 需要动态扩展时,可使用动态数组(如std::vector
  3. 链表实现时注意内存管理,避免内存泄漏
  4. 大对象存储时考虑智能指针

七、总结

栈是计算机科学中最基础的数据结构之一,其 LIFO 特性使其在程序执行、算法设计等领域发挥着不可替代的作用。通过掌握数组和链表两种实现方式,理解标准库容器的使用方法,能够帮助开发者更高效地解决实际问题。在具体应用中,应根据场景需求选择合适的实现方式,同时注意内存管理和性能优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值