赞
踩
采用链式存储的栈成为链栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现。
- typedef struct Linknode {
- int data; // 数据域
- struct Linknode* next; // 指针域
- } LiStack; // 栈类型定义
- // 初始化链栈的函数
- bool InitLiStack(LiStack* top) {
- top = (LiStack*)malloc(sizeof(LiStack)); // 分配头结点的内存
- if (top == NULL) {
- return false; // 分配失败,返回false
- }else{
- top->data = 0; // 初始化数据域,这里可根据需要设置
- top->next = NULL; // 头结点的next指针指向NULL
- return true; // 分配成功,返回true
- }
栈的链式存储操作其实和单链表的头插法插入很相似,我们完全可以使用单链表的头插法插入元素来模拟入栈操作
- //进栈操作
- bool Push(LiStack* top, int value) {
- LiStack* newNode = (LiStack*)malloc(sizeof(LiStack));//分配新结点的内存
- if (newNode == NULL) {
- return false;//分配失败,返回false
- }
- else {
- newNode->data = value;//设置新结点的数据域
- newNode->next = top;//新结点的next指针指向当前的栈顶
- top = newNode;//更新栈顶指针
- return true;//进栈成功,返回true
- }
- }
- //出栈操作
- bool Pop(LiStack* top, int* value) {
- if (top == NULL) {
- return false;
- }
- else {
- *value = top->data;//获取栈顶结点的数据
- LiStack* temp = top;//临时保存栈顶结点
- top = top->next;//更新栈顶指针
- free(temp);//释放栈顶结点内存
- return true;
- }
- }
在栈操作中,释放 temp
而不是 top
是因为 temp
指向的是即将被弹出的栈顶元素,而 top
指向的是新的栈顶元素。以下是详细解释:
栈的基本概念:栈是一种后进先出(LIFO)的数据结构。在栈中,最后插入的元素是最先被删除的。
出栈操作:出栈操作涉及从栈顶删除元素。在链式栈中,这意味着需要删除与 top
指针关联的节点。
temp
的作用:在出栈操作中,temp
被用来临时存储指向当前栈顶节点的指针。这样做的目的是,在删除当前栈顶节点后,top
指针可以安全地移动到下一个节点,而不会丢失对当前栈顶节点的引用。
释放 temp
:一旦 top
指针已经更新为指向下一个节点,temp
指向的节点就不再需要了。此时,释放 temp
指向的内存是安全的,因为它已经不再是栈的一部分。
不释放 top
:top
指针在出栈操作后仍然指向新的栈顶节点。如果释放了 top
指向的节点,那么 top
指针将指向一个已经被释放的内存区域,这将导致未定义行为,可能引发程序崩溃。
内存管理:在链式栈中,每个节点都是动态分配的内存。当一个节点被弹出栈时,必须释放该节点的内存,以避免内存泄漏。
代码实现:在您的代码中,free(temp)
正确地释放了即将被弹出的栈顶节点的内存。如果 free(top)
被错误地调用,那么 top
指针将指向一个无效的内存区域,这将破坏栈的结构。
总结来说,释放 temp
是因为 temp
指向的是即将被移除的栈顶节点,而 top
指向的是新的栈顶节点,需要保留以维护栈的结构。
- // 读取栈顶元素的值,不移除它
- bool Peek(LiStack* top, int* value) {
- if (top == NULL) {
- return false; // 栈为空,无法读取栈顶元素
- }
- else {
- *value = top->data; // 将栈顶元素的值赋给value指针指向的变量
- return true; // 成功读取栈顶元素
- }
在这个示例中,Peek
函数接受一个指向栈顶节点的指针 top
,以及一个指向 int
类型的指针 value
,用于存储栈顶元素的值。如果栈不为空,函数将栈顶元素的值赋给 value
指针指向的变量,并返回 true
。如果栈为空,则返回 false
。
在链式栈中,由于它是动态分配内存的,所以它不会像数组那样有固定的容量限制,也就不会出现“满”的情况。因此,我们只需要实现一个判断链栈是否为空的方法。
- bool IsEmpty(LiStack* stack) {
- return stack->top == NULL; // 如果栈顶指针为NULL,则栈为空
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。