动手敲代码——栈(经典问题练习)

/*用栈实现计算器*/ 
/*经典的用来练习栈的题目,需要借助逆波兰表达式*/

#include 
#include 
#include 

#define MAXSIZE 64
#define OK 1
#define ERROR 0

typedef struct
{
    int data[MAXSIZE];
    int top;
}stacknode;

/*创建一个顺序栈*/
stacknode * sqstack_create(void)
{
    stacknode * p;

    p = (stacknode *)malloc(sizeof(*p));
    assert(p);      //分配空间后加上断言是个好习惯
    p->top = -1;

    return p;
}

/*入栈操作*/
int sqstack_push(int n, stacknode * p)      
{
    if(p->top == (MAXSIZE - 1)) //栈满
    {
        return ERROR;
    }
    p->data[++p->top] = n;

    return OK;
}

/*出栈操作*/
int sqstack_pop(int *dest, stacknode * p)
{
    if(p->top == -1)    //栈空
    {
        return ERROR;
    }
    *dest = p->data[p->top--];

    return OK;
}

/*获取栈顶值*/
int sqstack_top(int *dest, stacknode *p)        //const修饰指针*p,p指向的内容不可改变
{
    if(p->top == -1)    //栈空
    {
        return ERROR;
    }
    *dest = p->data[p->top];

    return OK;
}

/*打印栈中内容*/
int sqstack_print(stacknode *p)
{
    int n = p->top;

    if(n == -1) //栈空
    {
        return ERROR;
    }
    while(n)
    {
        printf(" %d ",p->data[n--]);
    }
    printf(" %d ",p->data[n]);
    printf("\n");
}

/*判断栈是否为空*/
int sqstack_is_empty(stacknode *p)
{
    return (p->top == -1);
}

/*优先级判断函数*/
int get_priority(int ope)
{
    switch (ope)
    {
        case '+':
        case '-':return 1;
        case '*':
        case '/':return 2;
        case '(':return 0;
        default:return ERROR;
    }
}

/*提取两个数和一个操作符进行计算,得到的结果再压栈*/
void compute(stacknode *pnum,int ope)
{
    int num1,num2;
    int result;

    sqstack_pop(&num1,pnum);
    sqstack_pop(&num2,pnum);
    switch (ope)
    {
        case '+':   result = num1 + num2;
        case '-':   result = num1 - num2;
        case '*':   result = num1 * num2;
        case '/':   result = num1 / num2;
    }
    sqstack_push(result,pnum); 
}

/*进行优先级计算*/
void deal_ope(stacknode *pnum,stacknode *pope,int ope)
{
    int old_ope;

    if(sqstack_is_empty(pope)||ope == '(')  //当空栈或符号为( 时,将符号压栈后返回 
    {
        sqstack_push(ope,pope);
        return;
    }
    sqstack_top(&old_ope,pope);     //得到栈顶元素 
    if(get_priority(ope)>get_priority(old_ope))             //比较优先级,入参的符号优先级大于栈顶元素时, 将符号压栈后返回
    {
        sqstack_push(ope,pope);     
        return;
    }
    while(get_priority(ope)<=get_priority(old_ope))         
    {
        sqstack_pop(&old_ope,pope);
        compute(pnum,old_ope);      //以栈顶符号计算 后压栈 
        if(sqstack_is_empty(pope))
        {
            break;
        }
        sqstack_top(&old_ope,pope);     
    }
    sqstack_push(ope,pope); //将新的操作符入栈
}

//处理括号 ,进行括号里的高优先级计算,之后将计算结果压入数字栈,并且将括号丢弃 
void deal_bracket(stacknode *pnum,stacknode *pope)
{
    int old_ope;

    sqstack_top(&old_ope,pope);     //得到符号栈栈顶元素 
    while(old_ope != '(')           
    {
        sqstack_pop(&old_ope,pope);     //符号栈出栈 
        compute(pnum,old_ope);          //计算后将结果压入数字栈 
        sqstack_top(&old_ope,pope);     //得到栈顶元素,进行下一次循环 
    }
    sqstack_pop(&old_ope,pope);     //将( 出栈丢去 
}

int main()
{
    /*str为表达式数组*/
    char str[MAXSIZE];
    printf("请输入你要计算的表达式:\n");
    gets(str);

    int i = 0;
    int value = 0;   //数字的值
    int flag = 0;    
    int old_ope;

    stacknode *pnum,*pope;      // 定义两个指向栈结构体的指针

    pnum = sqstack_create();  // 创建存放数字的栈

    pope = sqstack_create();  // 创建存放运算符号的栈

    /* 表达式字符串解析函数,然后将高优先级的符号/(*)进行计算重新入栈
       退出while大家的优先级都一样+-*/
    while (str[i] != '\0')
    {
        //获取输入的数字
        if (str[i] >= '0' && str[i] <= '9')//num
        {
            value = value * 10 + str[i] - '0';
            flag = 1;
        }
        else//ope
        {
            if (flag)
            {
                //flag = 1说明value里面存储了数字,将其入栈
                sqstack_push (value, pnum);
                //num标志清零,value存放数字的变量清零
                flag = 0;
                value = 0;

            }
            if(str[i] == ')')
            {
                //如果是右括号,则
                deal_bracket(pnum,pope);    
            }
            else//+-*/(等情况 
            {
                deal_ope(pnum,pope,str[i]);
            }   
        }   
        i++;
    }

    //如果flag = 1.说明value里面还有数值,将其入栈 

    if (flag)
    {
        sqstack_push(value,pnum);
    }
    //然后将符号与数字依次出栈计算。数字出栈计算完成之后回再次在compute中入栈
    while (!sqstack_is_empty(pope))
    {
        sqstack_pop(&old_ope,pope);
        compute(pnum,old_ope);
    }
    //取出数字栈最后剩下的数字,就是最后的答案
    sqstack_pop(&value,pnum);
    //打印结果
    printf("%s = %d\n",str,value);

    return 0;
}

你可能感兴趣的:(数据结构和算法,栈)