使用链表实现栈(Stack)可以动态地管理内存,避免固定大小的限制。以下是使用C语言实现链表栈的代码:
链表栈的实现
#include
#include
// 定义链表节点结构
typedef struct Node {
int data; // 节点数据
struct Node *next; // 指向下一个节点的指针
} Node;
// 定义栈结构
typedef struct {
Node *top; // 栈顶指针
} Stack;
// 初始化栈
void initStack(Stack *s) {
s->top = NULL; // 栈顶指针初始化为NULL,表示栈为空
}
// 检查栈是否为空
int isEmpty(Stack *s) {
return s->top == NULL;
}
// 入栈操作
void push(Stack *s, int value) {
// 创建新节点
Node *newNode = (Node *)malloc(sizeof(Node));
if (newNode == NULL) {
printf("内存分配失败,无法入栈!\n");
return;
}
newNode->data = value;
newNode->next = s->top; // 新节点指向当前栈顶
s->top = newNode; // 更新栈顶指针
printf("入栈元素:%d\n", value);
}
// 出栈操作
int pop(Stack *s) {
if (isEmpty(s)) {
printf("栈为空,无法出栈!\n");
return -1; // 返回-1表示栈为空
}
Node *temp = s->top; // 临时保存栈顶节点
int value = temp->data; // 获取栈顶元素的值
s->top = s->top->next; // 栈顶指针指向下一个节点
free(temp); // 释放栈顶节点的内存
printf("出栈元素:%d\n", value);
return value;
}
// 获取栈顶元素(不删除)
int peek(Stack *s) {
if (isEmpty(s)) {
printf("栈为空,无栈顶元素!\n");
return -1; // 返回-1表示栈为空
}
return s->top->data;
}
// 打印栈内容
void printStack(Stack *s) {
if (isEmpty(s)) {
printf("栈为空!\n");
return;
}
printf("栈内容(从栈顶到栈底):");
Node *current = s->top;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
// 释放栈内存
void freeStack(Stack *s) {
while (!isEmpty(s)) {
pop(s); // 出栈并释放节点内存
}
}
int main() {
Stack s;
initStack(&s); // 初始化栈
push(&s, 10); // 入栈10
push(&s, 20); // 入栈20
push(&s, 30); // 入栈30
printStack(&s); // 打印栈内容
pop(&s); // 出栈
printStack(&s); // 打印栈内容
printf("栈顶元素:%d\n", peek(&s)); // 获取栈顶元素
pop(&s); // 出栈
pop(&s); // 出栈
pop(&s); // 尝试从空栈出栈
freeStack(&s); // 释放栈内存
return 0;
}
代码说明
- 链表节点结构:
data 存储节点数据。
next 指向下一个节点。
- 栈结构:
top 指向栈顶节点。
- 初始化栈:
将 top 初始化为 NULL,表示栈为空。
- 入栈操作:
创建新节点并添加到栈顶。
新节点的 next 指向当前栈顶,更新栈顶指针。
- 出栈操作:
检查栈是否为空。
获取栈顶节点的值,并更新栈顶指针。
释放栈顶节点的内存。
- 获取栈顶元素:
返回栈顶节点的值,但不删除它。
- 打印栈内容:
从栈顶到栈底遍历并打印所有节点。
- 释放栈内存:
通过出栈操作释放所有节点的内存。
- 主函数:
初始化栈。
进行入栈和出栈操作,并打印栈内容。
释放栈内存。
示例输出
复制
入栈元素:10
入栈元素:20
入栈元素:30
栈内容(从栈顶到栈底):30 20 10
出栈元素:30
栈内容(从栈顶到栈底):20 10
栈顶元素:20
出栈元素:20
出栈元素:10
栈为空,无法出栈!
总结
- 链表实现的栈可以动态扩展,不受固定大小的限制。
- 入栈和出栈操作的时间复杂度均为 O(1)。
- 需要手动管理内存,避免内存泄漏。