第四章 栈 (Stack)
4.1 栈的基本概念
栈是一种重要的数据结构,其特点是后进先出(LIFO, Last In First Out)。在栈中,最新添加的元素会最先被移除。栈在计算机科学中有着广泛的应用,例如在函数调用、表达式求值和递归处理中。
- 典型特性:
- 后进先出:栈中的元素按照逆序进行操作。
- 单端操作:栈的增删改查都发生在栈顶的一端。
栈的基本操作通常包括压栈(push)、弹栈(pop)、查看栈顶元素(peek)以及判断栈是否为空。
4.2 基于数组的栈
基于数组实现的栈使用数组来存储栈中的元素,操作简单且访问速度快。在C语言中,可以使用动态数组来避免数组大小固定的限制。
- 实现要点:
- 定义一个数组以及一个变量来表示栈顶位置。
- 压栈操作是将元素置于数组的下一空闲位置,然后栈顶指针增量。
- 弹栈操作是将栈顶指针减量后返回栈顶元素。
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
typedef struct {
int data[MAX_SIZE];
int top;
} Stack;
// 初始化栈
void initStack(Stack *s) {
s->top = -1;
}
// 判断栈是否为空
int isEmpty(Stack *s) {
return s->top == -1;
}
// 压栈操作
int push(Stack *s, int value) {
if (s->top == MAX_SIZE - 1) {
printf("栈满\n");
return -1;
}
s->data[++(s->top)] = value;
return 0;
}
// 弹栈操作
int pop(Stack *s) {
if (isEmpty(s)) {
printf("栈空\n");
return -1;
}
return s->data[(s->top)--];
}
// 查看栈顶元素
int peek(Stack *s) {
if (isEmpty(s)) {
printf("栈空\n");
return -1;
}
return s->data[s->top];
}
4.3 基于链表的栈
基于链表的栈解决了数组实现中栈大小固定的问题。使用链表节点来存储每个元素,可以动态调整栈的大小。
- 实现要点:
- 每个元素都是链表中的一个节点。
- 压栈将新节点插入链表头,弹栈删除链表头节点。
#include <stdio.h>
#include <stdlib.h>
// 定义节点
typedef struct Node {
int data;
struct Node *next;
} Node;
// 定义栈
typedef struct {
Node *top;
} Stack;
// 初始化栈
void initStack(Stack *s) {
s->top = NULL;
}
// 判断栈是否为空
int isEmpty(Stack *s) {
return s->top == NULL;
}
// 压栈操作
void push(Stack *s, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = value;
newNode->next = s->top;
s->top = newNode;
}
// 弹栈操作
int pop(Stack *s) {
if (isE