最近学算法学到了栈 写了一个典型例子逆波兰计算器。用很像链表的形式写的下面来看思路。
首先要做的是一个栈的模型具有压栈和出栈的功能
#include
#include
#define MAX_S 20
#define add 10
typedef double elem;
typedef struct node //为了方便修改 用了别名
{
elem *top; // 栈顶
elem *end; // 栈底
int length;// 长度
} Stack;
void create(Stack *e) //初始化栈
{
e->end = (elem *)malloc(MAX_S * sizeof(elem));
if(!e->end)
{
exit(0);
}
e->top = e->end;
e->length = MAX_S;
}
void push(Stack *e,elem s) //压栈
{
if(e->top-e->end>=e->length) //判断是否溢出 溢出则增加栈长度
{
e->end = (elem *)realloc(e->end,(e->length+add)*sizeof(elem));
if(!e->end)
{
exit(0);
}
}
*(e->top) = s;
e->top++;
}
void pop(Stack *e,elem *p) //出栈
{
if(e->top==e->end)
{
return;
}
e->top--;
*p = *(e->top);
// printf("%f",*p);
}
基本结构差不多就完成了 因为是动态栈运用了realloc来扩展空间,而且c语言比我想象地要智能,结构体指针相减得到的是相差多少个数据类型的值前提是类型要相等。
int size(Stack e) // 计算栈的长度
{
return (e.top-e.end);
}
void consolo(Stack *e) //输出栈中数据
{
Stack *pr = e;
pr->top = e->top;
int i = size(*e);
for(;i>=0;i--)
{
printf("%f\n",*(pr->top));
(pr->top)--;
}
}
这两个方法都是我在调试期间用的可以查看栈的长度和栈中数据
int isnumber(char e) //判断ascii是否为数字
{
if(e>=48 && e<=57)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
char test[add]={'\0'}; //数字缓冲区
int i=0;
char s;
double c1,c2,answer;
Stack stack;
create(&stack);
printf("输入逆波兰表达式数字和操作符用空格隔开最后以#结束\n");
do{
scanf("%c",&s);
while(isnumber(s) || s=='.') //转换为数字压入栈中
{
test[i] = s;
if(i>add){
printf("输入的单个数字长度过大!");
return -1;
}
i++;
scanf("%c",&s);
if(s == ' '){
c1 = atof(test);
push(&stack,c1);
i=0; //置空计数器
break;
}
}
switch(s)
{
case '+':
// consolo(&stack);
pop(&stack,&c1);
pop(&stack,&c2);
push(&stack,c2+c1);
break;
case '-':
pop(&stack,&c1);
pop(&stack,&c2);
push(&stack,c2-c1);
break;
case '*':
pop(&stack,&c1);
pop(&stack,&c2);
push(&stack,c2*c1);
break;
case '/':
pop(&stack,&c1);
pop(&stack,&c2);
if(c1==0){
printf("被除数不能为0");
return -1;
}
push(&stack,c2/c1);
break;
}
}while(s!='#');
pop(&stack,&answer);
printf("%f\n",answer);
return 0;
}
这就是主体了 因为有操作符的缘故所以不能直接使用整形或浮点型来控制 当遇到操作符的时候最好的方法就switch 然后通过空格来控制压入栈的数据以#来结束输入
ps. 因为太菜被出栈的指针坑了好一会 才发现要先减掉 栈顶指针永远指的空