数据结构实现 2.2:链表栈(C++版)
1. 概念及基本框架
通过第五节,我们知道链表虽然整体的操作时间复杂度是 O(n) 级别的,但是如果只对头结点进行操作,那么时间复杂度是 O(1) 级别的,这很类似于栈(单口容器)的操作。
在第二节中,我们利用 数组 实现了 栈 这种数据结构。当然,栈也可以通过 链表 来实现。下面通过链表来实现 链表栈 。
链表栈的结构如上图所示,链表栈有着栈的基本特性:
1.栈 有 栈顶 和 栈底 两端。
2.入栈 和 出栈 操作只能从 栈顶 进行。
3.后 入栈 的先 出栈 ,即 后进先出(Last In First Out),LIFO 。
与数组栈类似,依旧使用由 纯虚函数 构成的 抽象类 作为一个接口来定义栈的基本操作。具体代码如下:
template <class T>
class Stack{
public:
virtual int size() = 0;
virtual bool isEmpty() = 0;
virtual void print() = 0;
//入栈操作
virtual void push(T num) = 0;
//出栈操作
virtual void pop() = 0;
//获得栈顶元素
virtual T peek() = 0;
};
下面只需要通过继承 抽象类,并且重写 纯虚函数 ,就可以完成 链表栈 的实现。链表栈类的框架如下:
template <class T>
class LinkedListStack : public Stack<T>{
public:
LinkedListStack(){
}
...
private:
LinkedList<T> list;
};
这个类内部定义一个链表类对象,为了保护数据,把它放在 private 部分。因为 LinkedListStack 类包含了 LinkedList 类,所以构造函数 LinkedListStack 会自动调用 LinkedList 的构造函数。为了兼容更多类型,这里使用了泛型的概念。
2. 基本操作程序实现
2.1 入栈操作
template <class T>
class LinkedListStack : public Stack<T>{
public:
...
//入栈操作
void push(T num){
list.addFirst(num);
}
...
};
入栈操作使用了链表的增加第一个元素的操作来实现。
2.2 出栈操作
template <class T>
class LinkedListStack : public Stack<T>{
public:
...
//出栈操作
void pop(){
list.removeFirst();
}
...
};
出栈操作使用了链表的删除第一个元素的操作来实现。
2.3 查找操作
template <class T>
class LinkedListStack : public Stack<T>{
public:
...
//获得栈顶元素
T peek(){
return list.get(0);
}
...
};
因为栈只能获得栈顶元素,所以这里的查找操作也非常简单。
2.4 其他操作
template <class T>
class LinkedListStack : public Stack<T>{
public:
...
int size(){
return list.size();
}
bool isEmpty(){
return list