C++ 顺序栈结构构建与基础操作详解
本文详细讲解如何在 C++ 中构建顺序栈结构,涵盖从内存申请、状态判断到数据存取的核心步骤。通过具体的代码实现入栈、出栈、读取栈顶元素等操作,展示如何利用数组模拟栈的“后进先出”行为,并附带完整测试用例。
什么是栈结构
栈(Stack)是一种特殊的线性数据结构,其核心特征遵循“后进先出”(Last In First Out, LIFO)原则。可以将栈想象成一个垂直堆叠的箱子或仓库,新放入的物品必须放在最上面,而取出的物品也必然是最近放入的那个。
根据存储方式的不同,栈主要分为两类:
- 顺序栈:使用地址连续的内存单元(如数组)存储数据。通常定义一个固定大小的数组和一个指向栈顶的指针(
top),索引为 0 的位置通常视为栈底。 - 链式栈:基于链表结构实现,头节点指向栈顶,尾节点指针为空(NULL)指向栈底。
在栈中,只允许在一端(栈顶)进行插入(入栈)和删除(出栈)操作,另一端(栈底)保持不变。
准备数据结构与常量定义
在实现顺序栈之前,需要定义存储数据的结构体以及栈本身的容器结构。为了便于理解,我们设定下标从 1 开始有效使用,下标 0 保留不存数据。
定义最大长度 MAXLEN,数据单元结构 DATA,以及栈结构 StackType。
#define MAXLEN 50
struct DATA {
string name;
int age;
};
struct StackType {
DATA data[MAXLEN+1]; // 预留空间,索引1~MAXLEN有效
int top; // 栈顶指针
};
在这里,data 数组用于存储实际数据,top 变量记录当前栈顶元素的索引。当 top=0 时,表示栈为空;当 top=MAXLEN 时,表示栈已满。
核心操作功能实现
顺序栈的操作主要包括初始化和销毁栈空间,以及检查栈的状态(空/满)、清除数据和执行压栈/弹栈动作。
第 1 步:初始化栈结构
目的:分配内存并将栈顶指针置零,创建空栈。
入口:无参数。
动作:
1. 使用 new 运算符动态申请 StackType 大小的内存空间。
2. 若申请成功,将 p->top 设为 0,返回指针。
3. 若申请失败,返回 NULL。
StackType *STInit() {
StackType *p;
if(p=new StackType) // 申请栈空间
{
p->top=0; // 设置栈顶为0,表示空栈
return p; // 返回栈顶指针
}
return NULL; // 申请失败返回空指针
}
第 2 步:判断空栈与满栈
目的:在执行入栈或出栈前,确保操作的安全性。空栈不能出栈,满栈不能入栈。
判断空栈 (STIsEmpty):
检查 s->top == 0。如果为真,说明栈中没有元素。
int STIsEmpty(StackType *s) {
int t;
t=(s->top==0); // 通过栈顶的值进行判断
return t;
}
判断满栈 (STIsFull):
检查 s->top == MAXLEN。如果为真,说明栈空间已用完,无法再存入新数据。
int STIsFull(StackType *s) {
int t;
t=(s->top==MAXLEN);
return t;
}
第 3 步:清空与释放空间
清空栈 (STClear):
注意:这只是逻辑上的清空,即将 top 重置为 0。原有的数据仍然存在于内存中,但会被新加入的数据覆盖。这在复用栈对象时非常有用,无需重新分配内存。
void STClear(StackType *s) {
s->top=0;
}
释放空间 (STFree):
使用 delete 运算符释放由 new 分配的内存块,防止内存泄漏。通常在程序结束或不再需要该栈时调用。
void STFree(StackType *s) {
delete s;
}
第 4 步:入栈操作 (Push)
目的:将新数据元素保存到栈顶。
流程:
1. 首先检查栈是否溢出(top + 1 > MAXLEN)。如果溢出,打印错误信息并返回 0。
2. 若未溢出,先将栈顶指针加 1(++s->top),然后在新位置存入数据。
int PushST(StackType *s, DATA data) {
if((s->top+1) > MAXLEN) {
cout << "栈溢出" << endl;
return 0;
}
s->data[++s->top] = data; // 先移动指针,再存入数据
return 1;
}
第 5 步:出栈操作 (Pop)
目的:弹出栈顶元素并返回其地址。
流程:
1. 检查栈是否为空(s->top == 0)。如果为空,报错并退出程序。
2. 返回当前栈顶元素地址,并将 top 减 1(s->top--)。
DATA * PopST(StackType *s) {
if(s->top == 0) {
cout << "栈为空,不能再输出!" << endl;
exit(0);
}
return &(s->data[s->top--]); // 先取值,后指针减1
}
第 6 步:读取栈顶元素 (Peek)
目的:仅查看栈顶数据,而不改变栈的状态。
区别:与 Pop 不同,Peek 不会修改 top 指针,因此后续操作仍能访问该元素。
DATA * PeekST(StackType *s) {
if(s->top == 0) {
cout << "栈已空" << endl;
exit(0);
}
return &(s->data[s->top]); // 指针不变,直接返回地址
}
完整示例与运行结果
将上述所有组件组合,并通过主函数演示入栈、出栈、显示栈顶以及批量清空的过程。用户可连续输入姓名和年龄进行压栈,输入 "0" 结束输入。
#include <iostream>
#include <string>
using namespace std;
#define MAXLEN 50
struct DATA {
string name;
int age;
};
struct StackType {
DATA data[MAXLEN+1];
int top;
};
// ... [此处省略各函数定义,参考上文章节] ...
int main() {
StackType *stack;
DATA data, *p_data;
stack = STInit();
cout << "===============入栈操作:=============" << endl;
cout << "输入姓名 ,年龄进行入栈操作:" << endl;
// 执行入栈操作
while(1) {
cin >> data.name >> data.age;
if(data.name == "0") break;
else PushST(stack, data);
}
p_data = PopST(stack);
cout << "弹出栈顶元素" << endl;
cout << "name:" << p_data->name << ",age:" << p_data->age << endl;
p_data = PeekST(stack);
cout << "输出栈顶元素" << endl;
cout << "name:" << p_data->name << ",age:" << p_data->age << endl;
cout << "================将所有的的数据出栈:=============" << endl;
while(1) {
p_data = PopST(stack);
cout << "name:" << p_data->name << ",age:" << p_data->age << endl;
}
STFree(stack);
return 0;
}
程序运行后,首先等待用户输入数据并存入栈中。随后展示最后一次弹出的元素,紧接着展示剩余栈中的最新栈顶元素(通过 Peek 获取),最后循环将所有剩余数据按逆序弹出,验证“后进先出”的特性。
以上就是 C++ 中顺序栈结构建立与操作的详细内容,更多关于 C++ 数据结构栈应用实践的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













