前言
栈(Stack) 是一种 ** 后进先出(LIFO, Last In First Out)的线性数据结构。 它只允许在一端(栈顶)** 进行插入、删除操作,另一端(栈底)封闭。
栈的应用场景极广:
函数调用栈
表达式求值(计算器)
括号匹配
浏览器前进后退
操作系统中断现场保护
一、顺序栈是什么?
顺序栈 = 用动态数组实现的栈
特点:
底层是连续内存空间
支持自动扩容(避免溢出)
访问、插入、删除效率极高 O(1)
实现简单、稳定、不易出错
二、顺序栈结构体设计及支持的操作
cpp
#pragma once
#include<stdio.h>
typedef char ELEM_TYPE; // 数据类型(可改为 int/double 等)
#define INITSIZE 10 // 初始容量
// 顺序栈结构体
struct Seq_Stack
{
ELEM_TYPE* base; // 动态数组起始地址
int top; // 栈顶指针(下标)
int stacksize; // 当前总容量
};
typedef struct Seq_Stack Seq_Stack;
typedef struct Seq_Stack* PSeq_Stack;
// 1. 初始化
void Init_Stack(Seq_Stack* ps);
// 2. 入栈
bool Push(Seq_Stack* ps, ELEM_TYPE val);
// 3. 出栈
bool Pop(Seq_Stack* ps);
// 4. 获取栈顶元素
ELEM_TYPE Top(Seq_Stack* ps);
// 5. 判空
bool Is_Empty(Seq_Stack* ps);
// 6. 判满
bool Is_Full(Seq_Stack* ps);
// 7. 扩容
static void Inc(Seq_Stack* ps);
// 8. 获取长度
int Get_Length(Seq_Stack* ps);
// 9. 清空
void Clear(Seq_Stack* ps);
// 10. 销毁(释放内存)
void Destroy(Seq_Stack* ps);
// 11. 打印
void Show(Seq_Stack* ps);
结构说明
-
base:指向动态分配的数组
-
top :始终指向下一个可入栈的位置
-
top == 0→ 空栈 -
top == stacksize→ 栈满
-
-
stacksize:当前数组总容量(可扩容)
三、核心函数逐行精讲(最关键)
1. 初始化
cpp
//初始化
void Init_Stack(Seq_Stack* ps)
{
assert(ps != NULL);
// 分配初始容量
ps->base = (ELEM_TYPE*)malloc(INITSIZE * sizeof(ELEM_TYPE));
if (ps->base == NULL)
exit(1);
ps->top = 0;
ps->stacksize = INITSIZE;
}
作用:申请内存、设置栈空、容量初始化。
2. 入栈(Push)
cpp
bool Push(Seq_Stack* ps, ELEM_TYPE val)
{
assert(ps != NULL);
// 满了就扩容 2 倍
if (Is_Full(ps))
Inc(ps);
ps->base[ps->top] = val;
ps->top++;
return true;
}
时间复杂度 O(1)
自动扩容,永不溢出
3. 出栈(Pop)
cpp
bool Pop(Seq_Stack* ps)
{
assert(ps != NULL);
if (Is_Empty(ps))
return false;
ps->top--;
return true;
}
出栈不删除数据,只移动栈顶指针,高效!
4. 获取栈顶元素(Top)
cpp
ELEM_TYPE Top(Seq_Stack* ps)
{
assert(ps != NULL);
if (Is_Empty(ps))
exit(1);
return ps->base[ps->top - 1];
}
5. 扩容函数(Inc)
cpp
static void Inc(Seq_Stack* ps)
{
assert(ps != NULL);
ELEM_TYPE* tmp = (ELEM_TYPE*)realloc(ps->base, 2 * ps->stacksize * sizeof(ELEM_TYPE));
if (tmp != NULL)
ps->base = tmp;
ps->stacksize *= 2;
}
自动扩容为原来的 2 倍,避免频繁申请内存。
6. 清空栈
cpp
void Clear(Seq_Stack* ps)
{
assert(ps != NULL);
ps->top = 0;
}
不释放内存,只置空。
7. 销毁栈
cpp
//销毁 需要free
void Destroy(Seq_Stack* ps)
{
assert(ps != NULL);
free(ps->base);
ps->base = NULL;
ps->top = ps->stacksize = 0;
}
必须销毁! 防止内存泄漏。
8. 打印栈
cpp
void Show(Seq_Stack* ps)
{
assert(ps != NULL);
for (int i = 0; i < ps->top ; i++)
{
cout << ps->base[i] << " ";
}
cout << endl;
}
9. 判空、判满、获取有效长度值
cpp
//判空
bool Is_Empty(Seq_Stack* ps)
{
return ps->top == 0;
}
//判满
bool Is_Full(Seq_Stack* ps)
{
return ps->top == ps->stacksize;
}
//获取有效长度值
int Get_Length(Seq_Stack* ps)
{
assert(ps != NULL);
return ps->top;
}
四、测试主函数(可直接运行)
cpp
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
#include<stdlib.h>
#include"顺序栈.h"
using namespace std;
int main()
{
Seq_Stack head;
Init_Stack(&head);
Push(&head, 'A');
Push(&head, 'B');
Push(&head, 'C');
Show(&head);
cout << "长度: " << Get_Length(&head) << endl;
cout << "栈顶元素: " << Top(&head) << endl;
Pop(&head);
Show(&head);
return 0;
}
运行结果

五、顺序栈特点总结
连续内存,访问速度快
O (1) 入栈、出栈、取栈顶
动态扩容,不会溢出
实现简单、稳定
无野指针、无内存泄漏
六、高频考点(必背)
-
**栈的特点是什么?**后进先出(LIFO)。
-
顺序栈和链式栈区别?
-
顺序栈:连续内存、速度快、需扩容
-
链式栈:离散内存、不用扩容、速度稍慢
-
-
**顺序栈扩容为什么是 2 倍?**减少扩容次数,平衡时间与空间。
-
top 指针的含义? 指向下一个可入栈的位置。
-
清空和销毁的区别?
-
清空:只置空,不释放内存
-
销毁:释放所有内存
-
-
时间复杂度? 入栈、出栈、取栈顶:O(1)