实现一个整形栈

代码:

cpp 复制代码
#include <iostream>
#include <stdexcept> // 用于 std::out_of_range

class IntStack {
private:
    int* _data;        // 动态数组指针,指向堆上的内存
    size_t _capacity;  // 栈的总容量(数组大小)
    size_t _top;       // 栈顶索引(指向下一个可插入位置,也代表当前元素个数)

    // 私有辅助函数:扩容
    void resize() {
        size_t new_capacity = _capacity * 2;
        int* new_data = new int[new_capacity]; // 1. 分配新内存

        // 2. 复制旧数据
        for (size_t i = 0; i < _top; ++i) {
            new_data[i] = _data[i];
        }

        // 3. 释放旧内存并更新指针
        delete[] _data;
        _data = new_data;
        _capacity = new_capacity;
    }

public:
    // 1. 构造函数
    explicit IntStack(size_t init_size = 10) 
        : _capacity(init_size), _top(0) {
        if (init_size == 0) {
            _data = nullptr;
        } else {
            _data = new int[_capacity];
        }
    }

    // 2. 析构函数 (三法则之一)
    ~IntStack() {
        delete[] _data; // 释放堆内存
    }

    // 3. 拷贝构造函数 (三法则之一)
    IntStack(const IntStack& other) 
        : _capacity(other._capacity), _top(other._top) {
        if (_capacity == 0) {
            _data = nullptr;
        } else {
            _data = new int[_capacity];
            for (size_t i = 0; i < _top; ++i) {
                _data[i] = other._data[i];
            }
        }
    }

    // 4. 赋值运算符 (三法则之一)
    IntStack& operator=(const IntStack& other) {
        if (this != &other) { // 防止自赋值
            // 1. 申请新资源
            int* new_data = nullptr;
            size_t new_capacity = other._capacity;
            if (new_capacity > 0) {
                new_data = new int[new_capacity];
                for (size_t i = 0; i < other._top; ++i) {
                    new_data[i] = other._data[i];
                }
            }

            // 2. 释放旧资源
            delete[] _data;

            // 3. 更新状态
            _data = new_data;
            _capacity = new_capacity;
            _top = other._top;
        }
        return *this;
    }

    // 5. 元素个数
    size_t size() const {
        return _top;
    }

    // 6. 判空
    bool empty() const {
        return _top == 0;
    }

    // 7. 入栈
    void push(int value) {
        if (_top >= _capacity) {
            resize(); // 自动扩容
        }
        _data[_top++] = value; // 先赋值,再自增
    }

    // 8. 访问栈顶元素 (不删除)
    int& top() {
        if (empty()) {
            throw std::out_of_range("IntStack top() error: stack is empty");
        }
        return _data[_top - 1];
    }

    const int& top() const {
        if (empty()) {
            throw std::out_of_range("IntStack top() error: stack is empty");
        }
        return _data[_top - 1];
    }

    // 9. 出栈 (删除栈顶元素)
    void pop() {
        if (empty()) {
            throw std::out_of_range("IntStack pop() error: stack is empty");
        }
        --_top;
    }
};

该类主要由以下几个核心模块组成,每个模块都有其特定的作用:

1. 私有成员变量 (数据存储)

_data (int*): 这是一个指针,指向堆上分配的连续内存块(动态数组)。它是存储栈中所有元素的物理容器。

_capacity (size_t): 记录 _data 数组的总长度。表示栈最多能存多少个元素而不需要重新申请内存。

_top (size_t): 栈顶指针。这里采用的是"左闭右开"区间逻辑,_top 指向下一个待插入元素的位置 。因此,_top 的值也等于当前栈中元素的个数。

2. 辅助函数 resize()

作用 :当栈满(_top == _capacity)时,自动扩大存储空间。

用处:

  1. 申请一块两倍于当前容量的新内存。
  2. 将旧内存中的所有数据逐个复制到新内存。
  3. 释放旧内存,并让 _data 指向新内存
3. 构造函数 IntStack()

作用:初始化对象。

细节 :使用了 explicit 防止隐式类型转换。默认初始容量为 10。如果初始大小为 0,则将指针置空。

4. 析构函数 ~IntStack()

作用:清理资源。

关键点 :必须使用 delete[] 释放构造函数中 new 出来的数组。这是防止内存泄漏的关键。

5. 拷贝控制 (三法则)

为了管理动态内存,必须手动控制拷贝行为:

拷贝构造函数 :当用一个栈初始化另一个栈时调用。它执行深拷贝,即不仅复制指针,还复制指针指向的数据,确保两个栈互不影响。

赋值运算符:当一个栈被赋值给另一个已存在的栈时调用。它需要先释放自己原有的内存,再申请新内存复制数据,并处理自赋值的情况。

6. 核心接口

push(int): 入栈。先检查是否需要扩容,然后将元素放入 _data[_top] 位置,最后 _top 加 1。

pop(): 出栈。仅将 _top 减 1(逻辑上删除),不实际删除数据。

top(): 访问栈顶。返回 _data[_top - 1] 的引用,允许读写。如果栈空则抛出异常。

empty(): 通过判断 _top 是否为 0 来确定栈是否为空。

size(): 返回 _top 的值。

测试代码:

cpp 复制代码
int main() {
    IntStack s;
    s.push(10);
    s.push(20);
    
    std::cout << "Top: " << s.top() << std::endl; // 输出 20
    s.pop();
    std::cout << "Size: " << s.size() << std::endl; // 输出 1
    
    return 0;
}
相关推荐
夏鹏今天学习了吗2 小时前
【LeetCode热题100(98/100)】子集
算法·leetcode·深度优先
DuHz2 小时前
用于汽车应用的数字码调制(DCM)雷达白皮书精读
论文阅读·算法·自动驾驶·汽车·信息与通信·信号处理
李昊哲小课2 小时前
机器学习核心概念与经典算法全解析
人工智能·算法·机器学习·scikit-learn
风筝在晴天搁浅2 小时前
hot100 437.路径总和Ⅲ
算法
ShineWinsu3 小时前
对于C++:模版初阶的解析
开发语言·c++·面试·笔试·函数··模版
你怎么知道我是队长3 小时前
win11系统分盘2
c语言
sprintzer3 小时前
1.16-1.25力扣排序刷题
算法·leetcode·职场和发展
Max_uuc3 小时前
【C++ 硬核】告别 Excel 生成数组:利用 constexpr 实现编译期计算查找表 (LUT)
开发语言·c++·excel
老鼠只爱大米3 小时前
LeetCode经典算法面试题 #138:随机链表的复制(节点交织法、哈希表法等五种实现方案解析)
算法·leetcode·链表·随机链表复制·节点交织法