栈的链式存储结构
单链表有头指针,而栈顶指针也是必须的。
办法:将栈顶放在单链表的头部,不需要头结点。
链栈特点:
- 对于链栈来说,基本不存在栈满的情况,除非内存已经没有可以使用的空间。
- 对于空栈来说,链表原定义是头指针指向空,那么链栈的空其实就是 top = NULL的时候。
栈链的结构如下:
/* 链栈结构 */
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;
栈的链式结构——进栈操作
对于链栈的进栈 push 操作,假设元素值为 e 的新结点 是 s , top 为栈顶。
/* 插入元素e为新的栈顶元素 */
Status Push(LinkStack *S,SElemType e)
{
LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode));
s->data=e;
s->next=S->top; /* 把当前的栈顶元素赋值给新结点的直接后继,见图中① */
S->top=s; /* 将新的结点s赋值给栈顶指针,见图中② */
S->count++;
return OK;
}
栈的链式存储结构——出栈操作
假设变量 p 用来存储要删除的栈顶结点,将栈顶指针下移一位,最后释放 p 即可。
/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
Status Pop(LinkStack *S,SElemType *e)
{
LinkStackPtr p;
if(StackEmpty(*S))
return ERROR;
*e=S->top->data;
p=S->top; /* 将栈顶结点赋值给p,见图中③ */
S->top=S->top->next; /* 使得栈顶指针下移一位,指向后一结点,见图中④ */
free(p); /* 释放结点p */
S->count--;
return OK;
}
时间复杂度均为O(1)。
顺序栈与链栈对比
- 它们在时间复杂度上是一样的,均为O(1)。
- 对于空间性能,顺序栈需要事先确定一个固定的长度,可能会存在内存空间浪费的问题,优势:存取时定位方便。
- 而链栈要求每个元素都有指针域,这同时也增加了内存开销,但对于栈的长度无限制。