栈的链式存储结构
-
简称为链栈。
-
链栈的栈顶放在单链表的头部,顶替头结点。
-
链栈不存在栈满。
-
链栈为空是top=NULL。
-
链栈的存储结构:
typedef struct StackNode
{
sElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef strucf LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;
链栈的进栈
int Push(LinkStack *S, SElemType e)
{
LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode)); //新结点
s->data = e;
s->next = S->top; //把当前的栈顶元素赋值给新结点的直接后继。
S->top = s; //将新结点赋值给栈顶指针
S->count++; //栈顶元素移位
return 1;
}
- 时间复杂度为O(1)。
链栈的出栈
int Pop (LinkStack *S, SElemType *e)
{
LinkStackPtr p;
if (StackEmpty(*S)) //栈空
return 0;
*e = S->top->data;
p = S->top; //将栈顶结点赋值给p
S->top = S->top->next; //栈顶元素移位
free(p); //释放p
s->count--;
return 1;
}
- 时间复杂度为O(1)。
栈的应用
递归
-
定义:一个直接调用自己或者通过一系列调用语句间接的调用自己的函数,叫做递归函数。
-
必须至少有一个条件,使得满足条件后不再调用自身。
-
斐波那契数列:
//打印出前50位斐波那契数列
int Fbi(int i)
{
if( i < 2 )
return i == 0 ? 0 : 1; //若i==0,返回0。若i!=0,则返回1。
return Fbi(i - 1)+Fbi(i - 2); //调用自己
}
int main ()
{
int i;
for (int i = 0; i < 50; i++) //循环打印
printf("%d", Fbi(i));
return 0;
}
- 递归缺点:大量使用会建立函数的副本,消耗大量的时间和内存。
四则运算
-
后缀表达式:将算式通过后缀表达法转换表示后的表达式。(如:3+1/2=312/+)
-
通过栈将表达式转化为后缀表达式:
①遇到数字输出
②遇到第一个符号进栈
③遇到符号后若是左括号则进栈等待右括号进栈后,依次将括号内进栈的符号出栈输出(不输出左右括号)
④遇到非括号的符号与栈顶元素比较算数优先级,若高于栈顶元素则进栈,否则将栈顶元素出栈完毕后再进栈
⑤输出最后一个数字后,将栈内的符号依次出栈,结束。 -
后缀表达式的计算:
①遇到数字进栈
②遇到符号将栈顶元素依次出栈两个进行计算
③将计算结果再次入栈
④直到表达式完全计算完毕,结束。