Loading

堆栈

堆栈的应用场合

  1. 逆序输出:处理与输出次序的过程颠倒;递归深度与输出长度不易预知
  2. 递归嵌套
  3. 延迟缓存
  4. 栈式计算

逆序输出

进制转换

十进制转换为其他进制的过程,计算是从上至下,输出是从下往上

括号匹配:遇到‘(’就进栈,遇到‘ ) ’就出栈

扩展:多种括号匹配({},(),[]),无论是什么类的左括号,只要遇到左括号就入栈,遇到右括号就出栈。出栈时只有遇到相同类型的左括号才能是匹配成功,反之就是匹配失败。例如:[ ( ] )就是匹配失败的情况。HTML中的标签就是利用了括号匹配

延迟缓存

中缀求值: 处理多位数的方法:如果读到数字就放入操作数栈中,转向下一位,如果还是数字字符,就把操作数栈顶的数取出来*10,再加上这个数

后缀求值: 遇到操作数就入栈,遇到运算符就去栈中取出相应需要的操作数的个数,进行相应的计算,再把得到的结果放回栈中

栈混洗

一个序列根据一个栈中转而得到其他的序列

栈混洗总数(catalan数):(2n)! / (n!)*(n+1)!

表达式求值

/*
    中缀表达式转换后缀表达式
    思路:
        栈内<栈外:入栈操作符 
       栈内>=栈外:出栈操作符 
        遇到 ‘(’:直接入栈 
       遇到 ‘)’:出栈所有操作符直达遇到 ‘(’ 

    计算后缀表达式的值
    思路
        从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,
        遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

    补:
    中缀直接求值
    中缀表达式还有前缀表达并求值
    用二叉树转换中缀表达式到中缀表达式和中缀表达式
*/

# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define Max 1000 

typedef struct Node* NodeP;
typedef struct Node
{
    int Data[Max];
    int Top;
}Node;

NodeP S=NULL;
NodeP Head=NULL;

NodeP Creat()
{
    NodeP P=NULL;
    P=(NodeP)malloc(sizeof(Node));
    P->Top=-1;
    return P;
}

void Push(NodeP S,int ch)
{
    if(S->Top==Max-1)
    {
        printf("满\n");
        return;
    }
    S->Data[++S->Top]=ch;
    return;
}

int Top(NodeP S)
{
    int ch=0;
    if(S->Top==-1)
        return -1;
    ch=S->Data[S->Top];
    return ch;
}

int Pop(NodeP S)
{
    int ch=0;
    if(S->Top==-1)
    {
        printf("空\n");
        return 0;
    }
    ch=S->Data[S->Top--];
    return ch;
}

int Level(char ch)
{
    int m=0;
    switch(ch)
    {
        case '(': m=0;break;
        case ')': m=0;break;
        case '+': m=1;break;
        case '-': m=1;break;
        case '*': m=2;break;
        case '/': m=2;break;
        
    }
    return m;
}

void SuffixeExp(char* Head)             //中缀表达式转换后缀表达式函数
{
    int i=0;
    char ch;
    char* P=Head; 
    char A[1000]={'\0'};
    while(*P!='\0')
    {
        if(*P>=48 && *P<=57)
        {
            A[i++]=*P;
            if(*(P+1)<48 || *(P+1)>57)
                A[i++]=' ';                 //加空格是为了区分每个数
        }
        else
        {
            while(1)
            {
                ch=Top(S);          //堆栈空返回零  不然就返回操作符号
                if(ch>=0)
                {

                   if(*P=='(')              //遇到 ‘(’:直接入栈 
                    {
                        Push(S,(int)*P);
                        break;
                    }
                    if(Level(*P)>Level(ch))     //栈内<栈外:入栈操作符 
                    {

                        Push(S,(int)*P);
                        break;
                    }
                    else                        //栈内>=栈外:出栈操作符 
                    {
                        if(ch!='(')            
                        {
                            A[i++]=ch;
                            A[i++]=' ';
                            Pop(S);
                        }
                        else            //出栈所有操作符直达遇到 ‘(’ 
                        {
                            Pop(S);
                            break;
                        }
                    }

                }
                else                //堆栈为空直接入栈
                {   
                    Push(S,(int)*P);
                    break;
                }
            }

        }
        P++;
    }
    ch=Top(S);
    while(ch>=0)           //把栈内剩下的操作符全部输出
    {
        A[i++]=ch;
        A[i++]=' ';
        Pop(S);
        ch=Top(S);
    }
    A[i-1]='\0';
   strcpy(Head,A);  
    return;
}

void Evaluation(char* P)
{
    int sum=0;
    int top1=0,top2=0;
    while(*P!='\0')
    {
        if(*P>=48 && *P<=57)            //数字与数字还有表达式都是用空格隔开,所以循环求字符串表达的整数
            sum=sum*10+*P-'0';
        else if(*P==32)                 //如果为空格,并且前面为数字不是操作符号,那么入栈
        {
            if(*(P-1)>=48 && *(P-1)<=57)
            {
                Push(Head,sum);
                sum=0;
            }
        }
        else
        {
            top1=Pop(Head);         //如果是操作符,取栈顶两个元素进行计算
            top2=Pop(Head);
            int total=0;

            if(*P=='+')
                total=top2+top1;
            else if(*P=='-')
                total=top2-top1;
            else if (*P=='*')
                total=top2*top1;
            else
            {
                if (top1!=0)                //只要程序中有/号出现,一定要检测除数为零的情况
                {
                    total=top2/top1;
                }
                else
                {
                    printf("表达式错误,出现除数为零的情况出现\n");
                    return;
                }
            }
            Push(Head,total);
        }
        P++;
    }
    sum=Pop(Head);
    printf("%d\n",sum);
    return;
}

int main()  
{
    S=Creat();
    Head=Creat();
    char A[1000];
    scanf("%s",A);
    SuffixeExp(A);
    Evaluation(A);
    return 0;
}
posted @ 2021-05-30 20:12  兔子翻书  阅读(211)  评论(0)    收藏  举报