栈的链式存储简称链栈。
在链栈中将链表的头指针和栈顶指针合二为一。
对于链栈来说基本不存在栈满的情况,除非内存以及没有可用空间。对于空栈来说链表原定义是头指针指向空,那么链栈的空其实就是top==NULL的时候。
一、结构
typedef int SElemType;//此处可能是个结构体,练习使用int型足够了
typedef struct stacknode
{
SElemTypedata;
structstacknode * next;
}StackNode,* LinkStack;
二、栈的链式存储进栈操作
进栈操作,假设元素值为e新结点是s,top为栈顶指针则进栈操作如下:
算法思路:
1. 分配一个节点s;
2. 将结点值赋值给s->data;
3. 把当前栈顶元素赋值给新结点的直接后继;
4. 将新结点p赋值给栈顶。
三、栈的链式存储出栈操作
出栈操作,假设变量p用来存储要删除的栈顶结点,将栈顶指针下移一位,最后释放p即可。
算法思路:
1. 检查是否是空栈,空栈则返回;
2. 获取栈顶元素,将栈顶赋值给p;
3. 使得栈顶指针下移一位;
4. 释放p
四、时间复杂度
没有任何循环,时间复杂度都是O(1)。
对比一下顺序栈与链栈的时间复杂度均为O(1);空间复杂度上顺序栈需要提前分配一个固定的长度,可能会造成空间的浪费,但是它的优势是存取时候方便,并且链栈要求每个元素都有指针域,这同时也增加了一些内存开销,但是对于栈的长度无限制。所以链栈和顺序栈的区别和线性表中的讨论是一样的:如果栈的使用过程中元素变化不可预料,有时候很小,有时候非常大,那么最好使用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些。
五、代码示例
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define ERROR -1
#define OK 0
typedef int SElemType;//此处可能是个结构体,练习使用int型足够了
typedef struct stacknode
{
SElemType data;
struct stacknode * next;
}StackNode,* LinkStack;
//判栈空
int StackEmpty(LinkStack top)
{
if(top->next==NULL)
{
return 1;
}
else
{
return 0;
}
}
//入栈函数
LinkStack Push(LinkStack top,SElemType e)
{
StackNode * p = (StackNode *)malloc(sizeof(StackNode));
if(p != NULL)
{
p->data=e;
p->next=top->next;//把当前栈顶元素赋值给新结点的直接后继
top->next=p;//将新结点p赋值给栈顶
}
else
{
printf("分配结点失败\n");
}
return top;
}
//出栈函数
int Pop(LinkStack top)
{
StackNode * p;
SElemType t;
if(StackEmpty(top))
{
printf("空栈\n");
}
else
{
p = top->next;//将栈顶赋值给p
t = p->data;
top->next = p->next;//使得栈顶指针下移一位
free(p);
}
return t;
}
//打印函数
void PrintStack(LinkStack top)
{
if(top->next==NULL)
{
printf("空栈\n");
}
else
{
while(top->next!=NULL)
{
printf("元素:%d\n",top->next->data);
top=top->next;
}
}
}
//取栈顶元素
int StackTop(LinkStack top)
{
if(StackEmpty(top))
{
printf("空栈\n");
}
return top->next->data;
}
//栈的长度
int StackLen(LinkStack top)
{
int len=0;
while(top->next!=NULL)
{
len++;
top=top->next;
}
return len;
}
//销毁栈
void DestroyStack(LinkStack top)
{
LinkStack q;
while(top)
{
q=top->next;
free(top);
top=q;
}
printf("销毁成功");
}
//栈初始化
void InitStack(LinkStack top)
{
top->next=NULL;
}
int main()
{
int i = 0;
LinkStack top;
top = (LinkStack)malloc(sizeof(StackNode)); //注意
printf("\n=======初始化操作=========\n");
InitStack(top);
printf("\n=======入栈操作=========\n");
for(i = 0;i<10;i++)
{
Push(top,i); //入栈
}
printf("栈大小:%d\n",StackLen(top));
printf("\n=======打印栈信息=========\n");
PrintStack(top); //打印栈
printf("\n=======出栈操作=========\n");
if(top->next!=NULL)//出栈
{
printf("出栈元素::%d\n",Pop(top));
}
else
{
printf("空栈\n");
}
printf("\n=======取栈顶元素=========\n");
if(StackEmpty(top)==1)//取栈顶元素
{
printf("空栈\n");
}
else
{
printf("栈顶元素:%d\n",StackTop(top));
}
printf("\n=======判断栈是否为空=========\n");
if(StackEmpty(top)==1)//判断栈是否为空
{
printf("空栈\n");
}
else
{
printf("不是空栈\n");
}
printf("\n=======返回栈的元素个数=========\n");
if(StackEmpty(top)==1)//返回栈的元素个数
{
printf("空栈\n");
}
else
{
printf("栈大小:%d\n",StackLen(top));
}
printf("\n=======销毁栈=========\n");
DestroyStack(top);
return 0;
}