**1. 线性栈(顺序栈)**
结构定义:
cpp
#include <iostream>
using namespace std;
#define MAX_SIZE 100 // 预定义最大容量
// 线性栈结构体
typedef struct {
int* data; // 存储数据的数组
int top; // 栈顶指针(初始化为-1)
int capacity; // 当前栈的最大容量
} SeqStack;
// 初始化栈
void InitSeqStack(SeqStack& S) {
S.data = new int[MAX_SIZE];
S.top = -1;
S.capacity = MAX_SIZE;
}
// 销毁栈(释放内存)
void DestroySeqStack(SeqStack& S) {
delete[] S.data;
S.top = -1;
S.capacity = 0;
}
常见操作:
cpp
// 入栈
bool PushSeqStack(SeqStack& S, int x) {
if (S.top == S.capacity - 1) {
// 栈满时自动扩容(示例中扩容为原大小的2倍)
int newCapacity = S.capacity * 2;
int* newData = new int[newCapacity];
for (int i = 0; i <= S.top; i++) {
newData[i] = S.data[i];
}
delete[] S.data;
S.data = newData;
S.capacity = newCapacity;
}
S.data[++S.top] = x; // 栈顶指针先增1,再赋值
return true;
}
// 出栈
bool PopSeqStack(SeqStack& S, int& x) {
if (S.top == -1) {
cout << "栈空,无法出栈!" << endl;
return false;
}
x = S.data[S.top--]; // 先取栈顶元素,再减1
return true;
}
// 取栈顶元素
bool GetTopSeqStack(SeqStack& S, int& x) {
if (S.top == -1) return false;
x = S.data[S.top];
return true;
}
// 判空
bool IsEmptySeqStack(SeqStack& S) {
return S.top == -1;
}
2. 链栈
结构定义:
cpp
#include <iostream>
using namespace std;
// 链栈节点结构体
typedef struct LinkNode {
int data;
struct LinkNode* next;
} LinkNode;
// 链栈结构体(通过头指针管理)
typedef struct {
LinkNode* top; // 栈顶指针
} LinkStack;
// 初始化栈
void InitLinkStack(LinkStack& S) {
S.top = NULL; // 初始化为空栈
}
// 销毁栈(释放所有节点)
void DestroyLinkStack(LinkStack& S) {
LinkNode* p = S.top;
while (p) {
LinkNode* tmp = p;
p = p->next;
delete tmp;
}
S.top = NULL;
}
常见操作:
cpp
// 入栈
bool PushLinkStack(LinkStack& S, int x) {
LinkNode* newNode = new LinkNode;
if (!newNode) {
cout << "内存分配失败!" << endl;
return false;
}
newNode->data = x;
newNode->next = S.top; // 新节点指向原栈顶
S.top = newNode; // 更新栈顶指针
return true;
}
// 出栈
bool PopLinkStack(LinkStack& S, int& x) {
if (!S.top) {
cout << "栈空,无法出栈!" << endl;
return false;
}
LinkNode* tmp = S.top; // 保存栈顶节点
x = tmp->data; // 取栈顶数据
S.top = S.top->next; // 更新栈顶指针
delete tmp; // 释放旧栈顶节点
return true;
}
// 取栈顶元素
bool GetTopLinkStack(LinkStack& S, int& x) {
if (!S.top) return false;
x = S.top->data;
return true;
}
// 判空
bool IsEmptyLinkStack(LinkStack& S) {
return S.top == NULL;
}
3. 对比总结
特性 | **线性栈(顺序栈)** | 链栈 |
---|---|---|
存储结构 | 数组(连续内存) | 链表(离散内存) |
内存分配 | 静态预分配(可动态扩容) | 动态分配节点(按需增减) |
入栈操作 | data[++top] = x (可能需扩容) |
创建新节点并调整指针 |
出栈操作 | top-- (无需释放内存) |
释放节点内存 |
空间复杂度 | O(n)O(n)(预分配空间) | O(n)O(n)(每个节点含指针域) |
内存管理 | 整体一次性分配/释放 | 逐个节点分配/释放 |
适用场景 | 数据量固定或可预估 | 数据量动态变化,内存需求不确定 |
通过代码对比可以清晰看出:
- 线性栈 适合确定容量 或需要快速随机访问的场景(如函数调用栈)。
- 链栈 适合动态数据量 或需要灵活内存管理的场景(如递归算法)。