1 栈的定义
栈是一种数据结构,类似于枪的弹夹安装子弹,先安装的子弹最后弹出,后安装的子弹先弹出。
栈的具体定义:
typedef double ElemType;
typedef struct
{
ElemType *base;//指向栈底的指针变量
ElemType *top;//指向栈顶的指针变量
int StackSize;//当前最大容量
}sqStack;
2 栈的基本操作
- Init:栈的初始化
-Push(): 向栈中插入数据 - Pop():从栈中弹出数据
可以参考下图理解:
2.1 初始化操作
- 为栈底指针分配内存
- 将栈底指针赋值给栈顶指针,即战帝与栈顶指针指向同一位置,栈为空
- 给栈一个初始大小
void InitStack(sqStack *s)
{
s->base = (ElemType *)malloc(Stack_InitSize * sizeof(ElemType));
if (!s->base)
exit(0);
s->top = s->base;
s->StackSize = Stack_InitSize;
}
2.2 插入操作(入栈)
- 将元素赋值给顶部指针,此时顶部和底部指针都指向元素的地址
- 将顶部指针++,指向下一个空的地址。
void Push(sqStack *s,ElemType e)
{
*(s->top)= e;
s->top++;
}
2.3 弹出操作(出栈)
- 判断栈是否为空
- 让栈顶指针指向上一个元素
void Pop(sqStack *s,ElemType *e)
{
if (s->base == s->top)
return;
*e=*(--(s->top));
}
3 实战
逆波兰计算器:
逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出。逆波兰表达式又叫做后缀表达式。下面是一些例子:
正常的表达式 逆波兰表达式
- a+b —> a,b,+
- a+(b-c) —> a,b,c,-,+
- a+(b-c)d —> a,b,c,-,d,,+
- a+d*(b-c)—>a,d,b,c,-,*,+
- a=1+3 —> a,1,3,+,=
下面是具体代码:
#include<stdio.h>
#include<math.h>
#include<ctype.h>
#include<stdlib.h>
//支持小数点
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
#define MAXBUFFER 10
typedef double ElemType;
typedef struct
{
ElemType *base;
ElemType *top;
int StackSize;
}sqStack;
void InitStack(sqStack *s)
{
s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if (!s->base)
exit(0);
s->top = s->base;
s->StackSize = STACK_INIT_SIZE;
}
void push(sqStack *s, ElemType e)
{
if (s->top - s->base >= s->StackSize)
{
s->base = (ElemType*)realloc(s->base, (s->StackSize + STACKINCREMENT) * sizeof(ElemType));
if (!s->base) { exit(0); }
}
*(s->top) = e;
s->top++;
}
void pop(sqStack *s, ElemType *e)
{
if (s->top == s->base)
{
return;
}
*e = *--(s->top);
}
int StackLen(sqStack s)
{
return (s.top - s.base);
}
int main()
{
sqStack s;
char c;
double d, e;
char str[MAXBUFFER];
int i = 0;
InitStack(&s);
printf("请按照逆波兰表达式输入带计算数据,数据与运算符之间用空格隔开,以#作为结束标志:\n");
scanf_s("%c", &c);
while (c != '#')
{
while (isdigit(c) || c == '.')//用于过滤数据,若参数c为阿拉伯数字0~9,则返回非0值,否则返回0。
{
str[i++] = c;//缓冲区,可以将12连在一起
str[i] = '\0';
if (i >= 10)
{
printf("出错,输入单个数据过大!\n");
return -1;
}
scanf_s("%c", &c);
if (c == ' ')//有空格代表一个数据传入结束,比如12 3
{
d = atof(str);//将char型数字转化为double型,这个string是将 12 3将12合在一起了
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_s("%c", &c);
}
pop(&s, &d);
printf("\n最终的计算结果是:%f\n", d);
//system("pause");
return 0;
}
实现结果: