栈
目录
栈的定义
栈是一种数据结构,它具有以下特点:
-
只能在一端进行插入和删除操作,这一端被称为栈顶。
-
遵循"后进先出"(Last In First Out,LIFO)的原则。也就是说,最后进入栈的元素最先被弹出。
-
可以用数组或链表来实现。
例如,把书一本一本叠放在桌子上,只能从最上面取书或放书,这就类似栈的操作。后放上去的书先被拿走,符合"后进先出"原则。
栈的分类
栈主要有以下两种分类:
一、从存储结构角度分类
- 顺序栈:
-
利用一组连续的存储单元依次存放自栈底到栈顶的数据元素。
-
类似于在一个固定大小的数组中进行栈的操作,通过指针来指示栈顶位置。
-
优点是存储结构简单,容易实现,访问元素速度快。缺点是需要事先确定栈的大小,可能会出现栈溢出或空间浪费的情况。
- 链栈:
-
采用链表的形式存储栈元素,每个节点包含数据域和指向下一个节点的指针域。
-
栈顶在链表的头部,进行入栈和出栈操作时只需要修改栈顶指针。
-
优点是可以根据需要动态地分配内存空间,不会出现栈溢出的情况。缺点是需要额外的存储空间来存储指针,访问元素的速度相对较慢。
二、从应用场景角度分类
- 表达式求值栈:
-
在计算机中对算术表达式进行求值时,常常使用两个栈,一个用于存放操作数,另一个用于存放运算符。
-
通过特定的算法,根据运算符的优先级进行计算,实现表达式的求值。
- 函数调用栈:
-
当程序执行函数调用时,会将当前函数的状态(如返回地址、局部变量等)压入栈中。
-
当函数执行完毕后,从栈中弹出该函数的状态,恢复到调用前的状态,继续执行调用函数的后续代码。
栈的类型
顺序栈
1.栈的创建
cs
SeqStack* CreateSeqStack(int len)
{
SeqStack* ss = malloc(sizeof(SeqStack));
if(NULL == ss)
{
perror("create seq stack malloc");
return NULL;
}
ss->head= malloc(sizeof(DATATYPE)*len);
if(NULL == ss->head)
{
perror("create seq stack malloc2");
return NULL;
}
ss->tlen= len;
ss->top = 0;
return ss;
}
2.栈的销毁
cs
int DestroySeqStack(SeqStack* ss)
{
if(IsEmptySeqStack(ss))
{
free(ss);
return 0;
}
while(ss->top)
PopSeqStack(ss);
free(ss);
return 0;
}
3.入栈
cs
int PushSeqStack(SeqStack* ss, DATATYPE*data)
{
if(IsFullSeqStack(ss))
{
return 1;
}
memcpy(&ss->head[ss->top++],data,sizeof(DATATYPE));
return 0;
}
4.出栈
cs
int PopSeqStack(SeqStack*ss)
{
if(IsEmptySeqStack(ss))
{
return 1;
}
ss->top--;
return 0;
}
5.判断栈满
cs
nt IsFullSeqStack(SeqStack*ss)
{
return ss->tlen == ss->top;
}
6.判断栈空
cs
nt IsEmptySeqStack(SeqStack*ss)
{
return ss->top == 0;
}
7.获得栈顶元素
cs
DATATYPE* GetTopSeqStack(SeqStack* ss)
{
return &ss->head[ss->top-1];
}
8.判断栈长
cs
int GetSizeSeqStack(SeqStack*ss)
{
return ss->top;
}
链栈
1.栈的创建
cs
LinkStack* CreateLinkStack()
{
LinkStack* ls = (LinkStack*) malloc(sizeof(LinkStack));
if(NULL == ls)
{
perror("CreateSLinkList malloc");
return NULL;
}
ls->top = NULL;
ls->clen = 0 ;
return ls;
}
2.栈的销毁
cs
nt DestroyLinkStack(LinkStack*ls)
{
int len = GetSizeLinkStack(ls);
int i = 0 ;
for(i=0;i<len;i++)
{
PopLinkStack(ls);
}
free(ls);
return 0;
}
3.入栈
cs
int PushLinkStack(LinkStack*ls ,DATATYPE*data)
{
LinkStackNode*newnode = (LinkStackNode*)malloc(sizeof(LinkStackNode));
if(NULL == newnode)
{
perror("push malloc");
return 1;
}
memcpy(&newnode->data,data,sizeof(DATATYPE));
newnode->next = NULL;
newnode->next= ls->top;
ls->top = newnode;
ls->clen++;
return 0;
}
4.出栈
cs
int PopLinkStack(LinkStack*ls)
{
if(IsEmptyLinkStack(ls))
{
return 1;
}
LinkStackNode* tmp = ls->top;
ls->top=ls->top->next;
free(tmp);
ls->clen--;
return 0;
}
5.判断栈满
cs
nt IsFullLinkStack(SeqStack*ss)
{
return ss->top == ss->clne;
}
6.判断栈空
cs
int IsEmptyLinkStack(LinkStack*ls)
{
return ls->clen==0;
}
7.获得栈顶元素
cs
DATATYPE* GetTopLinkStack(LinkStack*ls)
{
if(IsEmptyLinkStack(ls))
{
return NULL;
}
else
{
return &ls->top->data ;
}
}
8.判断栈长
cs
int GetSizeLinkStack(LinkStack* ls)
{
return ls->clen;
}