一、类设计
template<class T>
class MyStack {
enum { STACK_INIT_SIZE = 10, STACK_INC_SIEZ = 2 }; // 初始容量为10,扩容倍数为2
T* _data; // 动态数组指针
int _size; // 栈总容量
int _top; // 栈顶索引(初始为-1,空栈)
public:
// 构造/拷贝构造/析构
MyStack(); // 默认初始化
MyStack(int sz); // 指定初始容量
MyStack(const MyStack& p); // 深拷贝构造
~MyStack(); // 释放内存
// 核心方法
bool Push(T x); // 入栈(含自动扩容)
T& Top() const; // 获取栈顶元素(可修改)
bool Pop(); // 出栈(仅移动指针)
T GetPOp(); // 出栈并返回元素
bool Empty() const; // 判空
bool Full() const; // 判满
int Size(); // 元素数量
};
二、核心实现细节
1. 动态内存管理
-
初始化:默认构造分配
STACK_INIT_SIZE
容量,用户可自定义初始容量。 -
深拷贝构造:
MyStack(const MyStack& p) : _size(0), _top(-1), _data(nullptr) { if (p._data != nullptr) { _size = p._size; _top = p._top; _data = new(nothrow) T[_size]; //分配内存 memcpy(_data, p._data, sizeof(T)*_size); //赋值 } }
-
避免浅拷贝问题(多对象共享内存导致重复释放)。
-
使用
nothrow
避免内存分配失败时抛出异常 。
-
-
析构:释放
_data
内存,重置指针和状态。
~MyStack()
{
delete[] _data;
_data = nullptr;
_size = 0;
_top = -1;
}
2. 动态扩容机制
-
触发条件:
Push
时检测栈满(_top + 1 == _size
)。 -
扩容:
bool Inc_Size() { T* new_data = new T[_size * STACK_INC_SIEZ]; // 扩容为原容量2倍 if (new_data == nullptr) { return false; } memcpy(new_data, _data, sizeof(T)*_size); // 复制旧数据 delete[] _data; // 释放旧内存 _data = new_data; _size *= 2; return true; }
-
若
new
分配失败,Inc_Size
返回false
,导致Push
失败。
-
3. 关键操作
-
入栈(Push):
-
栈满时触发扩容,失败返回
false
。 -
通过
_data[++_top] = x
实现高效插入。
-
bool Push(T x) // 入栈{
if (Full()){
if (Inc_Size()){
_data[_top + 1] = x;
_top++;
return true;
}
else return false;
}
else{
_data[++_top] = x;
return true;
}
}
-
出栈(Pop):
-
Pop()
仅移动_top
指针(不删除数据)。//只是出栈 bool Pop(){ if (Empty()) return false; _top -= 1; return true; }
-
GetPOp()
返回栈顶元素后调用Pop()
(会产生临时对象)。
-
// 取栈顶元素和出栈
T GetPOp(){
auto x = Top();
Pop();
return x;
}
-
栈顶访问(Top):
-
返回引用允许直接修改栈顶元素。
-
空栈时抛出
out_of_range
异常。
-
//取栈顶元素,元素不出栈
T& Top() const{
if(Empty()) throw out_of_range("Stack is empty!");
return _data[_top];
}