【概述】
链栈是采取链式存储的栈,其不存在栈满上溢的情况,通常采用不带头结点的单链表来实现,且一般规定所有的操作都在单链表表头进行,以保证出栈、入栈、取栈顶操作的时间复杂度为 $O(1)$
链栈的实现类如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| template <typename T> struct LNode { T data; LNode<T> *next; }; template <typename T> class LinkStack { public: LinkStack(); int getLen(); bool empty(); bool pop(T &elem); bool push(T elem); bool getTop(T &elem); void print(); private: LNode<T> *first; };
|
【初始化】
由于采用不带头结点的单链表,因此在初始化时直接令头指针指向为 NULL
即可
1 2 3 4
| template <typename T> LinkStack<T>::LinkStack() { first = NULL; }
|
【求栈长】
由于采用的是链式存储结构,因此在求栈长时,要从头指针开始枚举,枚举到链表尾部,时间复杂度为 $O(n)$
1 2 3 4 5 6 7 8 9 10
| template <typename T> int LinkStack<T>::getLen() { LNode<T> *p = first; int len = 0; while (p != NULL) { len++; p = p->next; } return len; }
|
【判空】
判空时,只需判断头指针 first
是否为 NULL
即可
1 2 3 4 5 6
| template <typename T> bool LinkStack<T>::empty() { if (first == NULL) return true; return false; }
|
【出栈】
在出栈时,首先进行下溢判断,之后令头指针指向的结点出栈,释放空间,再令头指针后移
1 2 3 4 5 6 7 8 9 10
| template <typename T> bool LinkStack<T>::pop(T &elem) { if (empty()) return false; LNode<T> *p = first; elem = p->data; first = first->next; free(p); return true; }
|
【入栈】
在入栈时,首先进行申请空间,之后采用头插法将新元素入栈
1 2 3 4 5 6 7 8 9 10
| template <typename T> bool LinkStack<T>::push(T elem) { LNode<T> *p = (LNode<T> *)malloc(sizeof(LNode<T>)); if (p == NULL) return false; p->data = elem; p->next = first; first = p; return true; }
|
【取栈顶】
在取栈顶时,首先进行下溢判断,之后输出头指针指向结点的数据域即可
1 2 3 4 5 6 7
| template <typename T> bool LinkStack<T>::getTop(T &elem) { if (empty()) return false; elem = first->data; return true; }
|
【输出】
在输出时,从栈顶开始,将栈中所有元素依次出栈,进行输出即可
1 2 3 4 5 6 7 8 9
| template <typename T> void LinkStack<T>::print() { int elem; while (!empty()) { pop(elem); cout << elem << " "; } cout << endl; }
|