(本文为根据b站小甲鱼的数据结构与算法视频所做笔记,供加强记忆和复习使用。)
栈的链式存储结构
简称栈链,栈因为只是栈顶来做插入和删除操作,所以较好的方法就是将栈顶放在单链表的头部,栈顶指针和单链表的头指针合体。
结构代码:
typedef struct StackNode
{
ElemType data;
struct StackNode *next;
} StackNode, *LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count
}
进栈操作:
对于栈链的Push操作,假设元素值为e的新节点是s,top为栈顶指针
Status Push(LinkStack *s, ElemType e)
{
LinkStackPtr p = (LinkStackPtr) malloc(sizeof(StackNode));
p->data = e;
p->next = s->top;
s->top = p;
s->count++;
return OK;
}
出栈操作:
对于栈链的出栈Pop操作,假设变量p用来存储要删除的栈顶结点,将栈顶指针下移一位,最后释放p即可。
Status Pop(LinkStack *s, ElemType *e)
{
LinkStackPtr p;
if( StackEmpty(*s))
{
return ERROR;
}
*e = s->top->data;
p = s->top;
s->top = s->top->next;
free(p);
s->count-- ;
return OK;
}
逆波兰表达式(RPN):
不需要括号的后缀表达式。
对于(1-2)*(4+5),用RPN表示法应该是这样:
1 2 - 4 5 + *
数字1和2近栈,遇到减号操作符则弹出两个元素进行运算并把结果入栈;
4和5入栈,遇到加号操作就弹栈,相加后将结果入栈;
然后遇到乘法运算符,将9和-1弹出栈进行乘法运算,此时栈空并无数据压栈,-9为最终运算结果。
假设所需头文件都引入了,初始化栈sqStack,Push,Pop,Len函数都已经写好(详情见之前的文章应该有写过或者去b站小甲鱼数据结构预算法视频系列p27)
int main
{
sqStack s;
char c;
double d,e;
char str[MAXBUFFER];
int i = 0;
InitStack(&s);
printf("请按逆波兰表达式输入待计算数据,数据与运算符之间用空格隔开,以#作为结束标志:");
scanf("%c", &c);
while(c != '#')
{
while(isdigit(c) || c=='.')
{
str[i++] = c;
str[i] = '\0';
if(i >= 10)
{
printf("出错,输入的单个数据过大! \n");
return -1;
}
scanf("%c", &c);
if(c == ' ')
{
d = atof(str);
Push(&s, d);
i = 0;
break
}
}
switch(c)
{
case '+':
Pop(&s, &e);
Pop(&s, &d);
Push(&s, d+e);
break;
case '-':
Pop(&s, &e);
Pop(&s, &d);
Push(&s, d-e);
break;
case '*':
Pop(&s, &e);
Pop(&s, &d);
Push(&s, d*e);
break;
case '/':
Pop(&s, &e);
Pop(&s, &d);
if(e != 0)
{
Push(&s, d/e);
}
else
{
printf("\n出错:除数为0!\n");
return -1;
}
break;
}
scanf("%c",&c);
}
Pop(&s, &d);
printf("\n最终的计算结果为: %f\n", d);
return 0;
}