链式栈深度解析
链式栈核心特性
graph TD
A[链式栈] --> B[动态内存分配]
A --> C[无容量限制]
A --> D[高效增删操作]
B --> E[避免内存浪费]
C --> F[适合不确定数据量场景]
D --> G[O(1)时间复杂度]
一、现代C++链式栈实现
模板类实现(智能指针版)
#include <memory>
#include <stdexcept>
template <typename T>
class LinkedStack {
private:
struct Node {
T data;
std::unique_ptr<Node> next;
explicit Node(T val) : data(val), next(nullptr) {}
};
std::unique_ptr<Node> top;
public:
LinkedStack() = default;
LinkedStack(const LinkedStack&) = delete;
LinkedStack& operator=(const LinkedStack&) = delete;
bool empty() const {
return !top;
}
void push(T value) {
auto newNode = std::make_unique<Node>(value);
newNode->next = std::move(top);
top = std::move(newNode);
}
T pop() {
if (empty()) {
throw std::out_of_range("Pop from empty stack");
}
T value = top->data;
top = std::move(top->next);
return value;
}
const T& peek() const {
if (empty()) {
throw std::out_of_range("Peek from empty stack");
}
return top->data;
}
~LinkedStack() = default;
};
关键优化点
- 智能指针管理:自动内存释放避免泄漏
- 异常安全:空栈操作抛出标准异常
- 移动语义:高效节点所有权转移
- 模板支持:泛型数据类型存储
- 禁用拷贝:防止意外复制导致资源问题
二、核心操作复杂度分析
操作 | 时间复杂度 | 空间复杂度 | 缓存友好性 |
---|
入栈(push) | O(1) | O(1) | ❌ |
出栈(pop) | O(1) | O(1) | ❌ |
查看栈顶(peek) | O(1) | O(1) | ❌ |
注:链式结构因指针跳转导致缓存不友好,适合低频大对象存储
三、扩展功能
1. 线程安全栈
#include <mutex>
template <typename T>
class ConcurrentStack {
LinkedStack<T> stack;
mutable std::mutex mtx;
public:
void push(T value) {
std::lock_guard<std::mutex> lock(mtx);
stack.push(value);
}
T pop() {
std::lock_guard<std::mutex> lock(mtx);
return stack.pop();
}
bool empty() const {
std::lock_guard<std::mutex> lock(mtx);
return stack.empty();
}
};
2. 迭代器支持
class Iterator {
Node* current;
public:
explicit Iterator(Node* node) : current(node) {}
T& operator*() { return current->data; }
Iterator& operator++() {
if (current) current = current->next.get();
return *this;
}
bool operator!=(const Iterator& other) {
return current != other.current;
}
};
Iterator begin() { return Iterator(top.get()); }
Iterator end() { return Iterator(nullptr); }
四、典型应用场景
1. 函数调用栈模拟
2. 浏览器历史记录
class BrowserHistory {
LinkedStack<std::string> backStack;
LinkedStack<std::string> forwardStack;
public:
void visit(const std::string& url) {
backStack.push(url);
forwardStack = LinkedStack<std::string>();
}
std::string back() {
if (backStack.empty()) return "";
forwardStack.push(backStack.pop());
return backStack.peek();
}
std::string forward() {
if (forwardStack.empty()) return "";
backStack.push(forwardStack.pop());
return backStack.peek();
}
};
五、最佳实践指南
1. 实现选择建议
场景 | 推荐方案 | 说明 |
---|
高频小对象操作 | 数组栈 | 缓存友好 |
大对象存储 | 链式栈 | 避免内存复制 |
多线程环境 | 并发安全栈 | 保证线程安全 |
需要遍历操作 | 迭代器支持 | 提供遍历接口 |
2. 内存管理技巧
template <typename T>
class NodePool {
std::stack<std::unique_ptr<Node>> pool;
public:
std::unique_ptr<Node> acquire(T val) {
if (pool.empty()) {
return std::make_unique<Node>(val);
}
auto node = std::move(pool.top());
pool.pop();
node->data = val;
return node;
}
void release(std::unique_ptr<Node> node) {
pool.push(std::move(node));
}
};
六、扩展阅读与测试
单元测试示例
TEST(LinkedStackTest, BasicOperations) {
LinkedStack<int> stack;
ASSERT_TRUE(stack.empty());
stack.push(10);
ASSERT_FALSE(stack.empty());
ASSERT_EQ(stack.peek(), 10);
ASSERT_EQ(stack.pop(), 10);
ASSERT_TRUE(stack.empty());
}
TEST(LinkedStackTest, ExceptionSafety) {
LinkedStack<int> stack;
ASSERT_THROW(stack.pop(), std::out_of_range);
ASSERT_THROW(stack.peek(), std::out_of_range);
}