C语言栈的链式存储实现:从创建到入栈出栈操作详解
本文深入解析C语言中数据结构的链式栈实现。通过定义包含top和bottom指针的结构体,利用尾插法建立初始数据,并逐步演示入栈、出栈、打印及长度计算等关键操作步骤,提供完整的可运行代码示例。
链式栈的核心设计思路
链式栈是一种基于链表实现的栈结构,其优势在于内存分配的动态性,不需要预先设定固定大小。在C语言实现中,通常使用两个关键指针来维护栈的状态:
- top 指针:始终指向栈顶元素,即最后进入的元素。所有入栈(Push)和出栈(Pop)操作都围绕此指针进行。
- bottom 指针:指向链表的头部(通常作为辅助标记),便于从头遍历整个栈或进行其他辅助操作。
第1步:构建基础数据结构
实现栈的首要任务是定义表示单个节点的 struct node 和表示栈整体的 struct stack。代码中特别使用了 date 字段存储整型数据(注:此处为原稿变量命名,实际编程中建议使用更具语义的名称如 data)。
#include<stdio.h>
#include<stdlib.h>
// 节点结构体,包含数据和指向下一节点的指针
struct node {
int date;
struct node *next;
};
// 栈结构体,包含底部指针和顶部指针
struct stack {
struct node *bottom;
struct node *top;
} s;
第2步:初始化与创建空栈
创建一个空栈时,需要为栈结构体和第一个辅助节点分配内存。初始化后,top 和 bottom 均指向同一个新创建的节点,且该节点的 next 指针设为 NULL,以此标记栈为空。
struct stack *creat(struct stack *s) {
// 分配栈结构体内存
s=(struct stack *)malloc(sizeof(struct stack ));
// 分配首个节点内存,并同时赋给 top 和 bottom
s->bottom=s->top=(struct node *)malloc(sizeof(struct node));
// 清空指针,确保无野指针
s->top->next=NULL;
s->bottom->next=NULL;
return s;
}第3步:实现入栈操作 (Push)
入栈操作的逻辑是在当前 top 指向的节点之后插入新节点,并更新 top 指针指向新节点。题目要求采用“尾插入法”,即每次都在链表尾部追加元素。
void push(struct stack *s,int e) {
struct node *p;
// 为新元素分配内存
p=(struct node *)malloc(sizeof(struct node));
p->date=e; // 存入数据
p->next=NULL; // 新节点指向空
// 将新节点链接到当前栈顶之后
s->top->next=p;
// 更新栈顶指针
s->top=p;
}第4步:实现出栈操作 (Pop)
由于链式栈的定义中包含 bottom 指针,出栈时需要找到倒数第二个节点,将其 next 置为 NULL,并将 top 指针移动至该位置。这种方式能正确释放栈顶节点的后续连接,完成出栈。
void pop(struct stack *s) {
struct node *p,*q;
p=s->bottom; // 从头开始遍历
while(p->next!=NULL) {
q=p;
p=p->next;
}
// 此时 p 指向最后一个节点(原栈顶),q 指向其前驱
q->next=NULL; // 断开与原栈顶的连接
s->top=q; // 更新栈顶指针
}第5步:遍历打印与长度计算
为了验证栈的状态,我们需要实现遍历和长度统计功能。遍历时跳过 bottom 指向的首个空节点,直接从其后继节点开始输出。长度计算则通过循环递增计数器实现。
void print(struct stack *s) {
struct node *p = s->bottom->next;
while(p!=NULL) {
printf("%4d",p->date);
p=p->next;
}
}
void length(struct stack *s) {
struct node *p=s->bottom->next;
int i=0;
while(p!=NULL) {
i++;
p=p->next;
}
printf("此时栈的长度为:%4d",i);
}完整测试流程与结果分析
以下代码演示了完整的操作流程:首先创建栈并依次插入 67, 3, 88, 6, 1, 7, 0,随后插入 -9,接着执行三次出栈操作,最后打印剩余元素并显示长度。
int main() {
struct stack *s;
int e;
// 1. 初始化空栈
s=creat(s);
// 2. 尾插入法构建初始栈
push(s,67); push(s,3); push(s,88); push(s,6);
push(s,1); push(s,7); push(s,0);
printf("初始栈元素为:");
print(s);
printf("\n\n");
// 3. 入栈操作:插入 -9
push(s,-9);
printf("插入元素后:");
print(s);
printf("\n\n");
// 4. 出栈操作:连续弹出3次 (移除 -9, 0, 7)
pop(s); pop(s); pop(s);
printf("删除元素后:");
print(s);
printf("\n\n");
// 5. 查看当前长度
length(s);
return 0;
}通过上述操作,您可以清晰观察到链式栈 “后进先出” 的特性:最后插入的 -9 最先被弹出,紧随其后的是 0 和 7。这种动态管理内存的方式非常适合处理数据量不确定或频繁变化的应用场景。
以上就是C语言数据结构之栈链式实现的详细内容,更多关于C语言栈与指针操作的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













