C++数据结构1——栈结构详解
一、栈的基本概念与特性
1. 栈的定义与特点
栈(Stack)是一种遵循后进先出(LIFO, Last In First Out)原则的线性数据结构,其核心特征包括:
-  
单端操作:所有操作仅通过栈顶进行
 -  
动态存储:无需预先分配固定空间
 -  
使用方法:
通过对象. 函数 的方式调用 ,需要导入头文件 #include <stack> -  
定义类型 stack <类型> 名称;
例如stack <int> s; //s是一个栈,这个栈里的每一个元素都是 int类型 -  
声明与使用
-  
声明一个stack类型的对象(变量) stack<int> s;
 -  
栈声明完毕,是空栈,需要往里面添加数据
s.push(i)
s.pop() 出栈
s.top() 获取栈顶元素,但并不出栈
s.size() 当前栈里有多少元素
s.empty() 判断栈是否为空,为空返回true, 不空返回false
 
 -  
 
2. 栈的物理结构
栈就是一个容器,这个容器只有一端开放,进出都必须经由开放的这一端,开放端,称为栈顶,
不开放的,称为栈底


二、数组模拟栈与STL栈对比
1. 数组模拟栈实现(十进制转二进制)
#include <iostream>
using namespace std; 
int main() { 
    int n; 
    int s[50] = {0};      // 存储二进制位的数组
    int top = 0;          // 栈顶指针(初始为0)
    cin >> n; 
    if(n == 0) {          // 处理特殊值
        cout << 0;
        return 0;
    }
    while (n > 0) { 
        s[top] = n % 2;   // 存储余数
        top++;            // 栈顶上移
        n /= 2; 
    } 
    // 逆序输出
    while (top > 0) { 
        cout << s[top - 1]; 
        top--;            // 栈顶下移
    }
    return 0; 
} 
关键点解析
| 变量 | 作用 | 操作逻辑 | 
|---|---|---|
s[50] | 模拟栈存储空间 | 静态数组预分配 | 
top | 栈顶指针 | top++表示入栈 | 
n | 待转换的十进制数 | 通过连续除2取余 | 
2. STL栈实现(通用进制转换)
#include <iostream>
#include <stack>
using namespace std;
int main() {
    int n, m;
    cin >> n >> m;        // 输入数值和进制基数
    
    stack<int> s;         // 声明整型栈
    
    if(n == 0) {          // 处理边界条件
        cout << 0;
        return 0;
    }
    while(n > 0) {
        s.push(n % m);    // 余数入栈
        n /= m;
    }
    while(!s.empty()) {   // 栈非空时循环
        cout << s.top();  // 输出栈顶元素
        s.pop();          // 移除栈顶元素
    }
    return 0;
} 
核心方法对比
| 操作 | 数组模拟栈 | STL栈 | 
|---|---|---|
| 入栈 | s[top++] = value | s.push(value) | 
| 出栈 | top-- | s.pop() | 
| 查看栈顶 | s[top-1] | s.top() | 
| 空栈判断 | top == 0 | s.empty() | 
| 内存管理 | 手动控制 | 自动扩容 | 
三、C++标准库栈容器详解
1. 模板化声明
#include <stack> // 声明不同类型的栈 stack<int> intStack; // 整型栈 stack<double> doubleStack; // 双精度浮点栈 stack<char> charStack; // 字符栈(适用于16进制)
2. 核心方法说明
| 方法 | 功能描述 | 示例 | 
|---|---|---|
push(val) | 元素入栈 | s.push(10) | 
pop() | 移除栈顶元素 | s.pop() | 
top() | 返回栈顶元素(不删除) | int x = s.top() | 
empty() | 判断栈是否为空 | if(s.empty()){...} | 
size() | 返回当前元素数量 | cout << s.size() | 
3. 类型安全示例
stack<string> historyStack;
// 浏览器历史记录管理
historyStack.push("首页");
historyStack.push("商品详情页");
historyStack.push("购物车");
// 模拟返回按钮操作
while(!historyStack.empty()) {
    cout << "返回至:" << historyStack.top() << endl;
    historyStack.pop();
} 
四、实战技巧与注意事项
1. 调试常见问题
-  
栈空访问:调用
top()或pop()前必须检查空栈if(!s.empty()) { int val = s.top(); s.pop(); } -  
数值溢出:处理大数时使用
long long类型 -  
进制范围:确认基数在合法范围内(2-16)
 
2. 性能优化建议
| 场景 | 优化策略 | 
|---|---|
| 高频入栈/出栈 | 预分配内存(数组栈) | 
| 大数转换 | 使用字符串存储中间结果 | 
| 多线程环境 | 采用线程安全容器 | 
3. 扩展应用场景
-  
表达式求值:处理括号匹配、运算符优先级
 -  
撤销/重做:记录操作历史
 -  
递归转迭代:用栈模拟递归调用过程
 
五、综合对比与选择建议
| 考量维度 | 数组模拟栈 | STL标准栈 | 
|---|---|---|
| 学习成本 | 需理解指针操作 | 接口简单易用 | 
| 内存控制 | 手动管理(易出错) | 自动扩容(更安全) | 
| 执行效率 | 直接内存访问(略快) | 有封装开销(可忽略) | 
| 功能扩展 | 可定制特殊功能 | 受限于标准接口 | 
| 适用场景 | 教学演示、嵌入式开发 | 商业项目、快速开发 | 
通过掌握数组模拟栈的实现原理与STL栈的标准用法,开发者可以灵活选择适合的栈实现方式。建议在算法竞赛中优先使用STL栈提升开发效率,在学习阶段通过手动实现加深对底层原理的理解。
