实现一个整形栈

代码:

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;
}
相关推荐
艾莉丝努力练剑3 小时前
【Linux:文件】Ext系列文件系统(初阶)
大数据·linux·运维·服务器·c++·人工智能·算法
Once_day3 小时前
C++之《程序员自我修养》读书总结(1)
c语言·开发语言·c++·程序员自我修养
Trouvaille ~3 小时前
【Linux】TCP Socket编程实战(一):API详解与单连接Echo Server
linux·运维·服务器·网络·c++·tcp/ip·socket
偷吃的耗子3 小时前
【CNN算法理解】:CNN平移不变性详解:数学原理与实例
人工智能·算法·cnn
坚果派·白晓明3 小时前
在鸿蒙设备上快速验证由lycium工具快速交叉编译的C/C++三方库
c语言·c++·harmonyos·鸿蒙·编程语言·openharmony·三方库
小镇敲码人3 小时前
深入剖析华为CANN框架下的Ops-CV仓库:从入门到实战指南
c++·python·华为·cann
dazzle4 小时前
机器学习算法原理与实践-入门(三):使用数学方法实现KNN
人工智能·算法·机器学习
那个村的李富贵4 小时前
智能炼金术:CANN加速的新材料AI设计系统
人工智能·算法·aigc·cann
风指引着方向4 小时前
图编译优化全链路:CANN graph-engine 仓库技术拆解
c语言