栈的学习(3)

栈学习中必做题--中缀表达式转换成后缀表达式(后缀表达式也叫逆波兰表达式)

列如(a+b)--ab+

首先用顺序存储来实现:

#include<stdio.h>
#include<stdlib.h>

char stack[100]={'\0'};

int compare(char s1,char s2);
int isblock();
void pop(int t);
void push(char s,int i);
int isnum(char s);
int main()
{
    char str[100]={'\0'};
    int i,t=0;
    gets(str);
    for(i=0;str[i]!='\0';i++)
    {
        if(isnum(str[i])) printf("%c",str[i]);
        else
        {
            if(isblock()) push(str[i],0);
            else if(compare(stack[t],str[i])==1) push(str[i],++t);
            else if(compare(stack[t],str[i])==2)
            {
                for(;compare(stack[t],str[i])==2;t--)
                    {
                        printf("%c",stack[t]);
                        pop(t);
                    }
                    push(str[i],++t);
            }
            else if(compare(stack[t],str[i])==0)
            {
                for(;stack[t]!='(';t--)
                {
                    printf("%c",stack[t]);
                   pop(t);//这里加不加这句都可以,按照逻辑加上为好
                }
                pop(t--);
            }
        }
    }
    if(t>=0)
    {
        for(;t>=0;t--)
            printf("%c",stack[t]);
    }
    return 0;
}

int isnum(char s)
{
    if(s=='a'||s=='b'||s=='c')
        return 1;
    else return 0;
}
void push(char s,int i)
{
    stack[i]=s;
}
void pop(int t)
{
    stack[t]='\0';
}
int isblock()
{
    if(stack[0]=='\0')
        return 1;
    else return 0;
}

int compare(char s1,char s2)
{
    if((s1=='+'||s1=='-')&&(s2=='*'||s2=='/')) return  1;
    else if((s1=='*'||s1=='/')&&(s2=='*'||s2=='/')) return 2;
    else if((s1=='+'||s1=='-')&&(s2=='+'||s2=='-')) return 2;
    else if((s1=='*'||s1=='/')&&(s2=='+'||s2=='-')) return 2;
    else if (s2=='('||s1=='(') return 1;
    else if(s2==')') return 0;
}

用教科书般的栈来实现中缀到后缀

#define STACKSIZE 20
typedef struct
{
    char *top;
    char *base;
    int stacksize;
}sqstack;


void initstack(sqstack *s)
{
    s->base=(char *)malloc(STACKSIZE*sizeof(char));
    if(!s->base)
        exit(0);
    s->top=s->base;
    s->stacksize=STACKSIZE;
}

void push(sqstack *s,char e)
{
    if(s->top-s->base>=s->stacksize)
    {
        s->base=(char *)realloc(s->stacksize,(s->stacksize+STACKSIZE)*sizeof(char));
        if(!s->base)
            exit(0);
    }
    *(s->top)=e;
    s->top++;
}

void pop(sqstack *s,char *e)
{
    if(s->base==s->top)
        {
            exit(0);
        }
    s->top--;
    *e=*(s->top);
}


int stacklen(sqstack s)
{
    return (s.top-s.base);
}


int main()
{
    sqstack s;
    initstack(&s);
    char c,e;
    printf("请输入中缀表达式\n");
    scanf("%c",&c);
    while(c!='\n')
    {
        while(c>='0'&&c<='9')//关键的地方,为了防止输入两位数以上的数字导致的错误
        {
            printf("%c",c);
            scanf("%c",&c);
            if(c<'0'||c>'9')
            {
                printf(" ");
            }
        }

        if(')'==c)//右括号,弹出元素,弹到左括号为止
        {

            pop(&s,&e);
            while(e!='(')
            {
            printf("%c ",e);
            pop(&s,&e);
            }
        }

        else if(c=='+'||c=='-')//+和-的优先级最低,只要是这两个,栈在非空时就要一直弹元素出来,弹到出现括号和空栈
   {
            if(!stacklen(s))
            {
                push(&s,c);
            }
            else
            {
                do
                {
                    pop(&s,&e);
                    if('('==e)
                    {
                        push(&s,e);
                    }
                    else
                    {
                        printf("%c ",e);
                    }
                }while(stacklen(s)&&'('!=e);
                push(&s,c);//不要忘记要把输入的元素压栈
            }
        }

        else if(c=='*'||c=='/'||c=='(')//优先级最高,必修压栈
        {
            push(&s,c);
        }
        else if(c=='\n')
        {
            break;
        }
        else
        {
            printf("输入有误");
            return -1;
        }


        scanf("%c",&c);
    }

    while(stacklen(s))//栈不为空时
    {
        pop(&s,&e);
        printf("%c ",e);
    }

    return 0;
}




逆波兰计算器:

列如:输入:9 3 1 - 3 * + 10 2 / +

输出为:20 

#define STACKSIZE 20
#include<ctype.h>
typedef struct
{
    double *top;
    double *base;
    int stacksize;
}sqstack;


void initstack(sqstack *s)
{
    s->base=(double *)malloc(STACKSIZE*sizeof(double));
    if(!s->base)
        exit(0);
    s->top=s->base;
    s->stacksize=STACKSIZE;
}

void push(sqstack *s,double e)
{
    if(s->top-s->base>=s->stacksize)
    {
        s->base=(double *)realloc(s->stacksize,(s->stacksize+STACKSIZE)*sizeof(double));
        if(!s->base)
            exit(0);
    }
    *(s->top)=e;
    s->top++;
}

void pop(sqstack *s,double *e)
{
    if(s->base==s->top)
        {
            exit(0);
        }
    s->top--;
    *e=*(s->top);
}


int stacklen(sqstack s)
{
    return (s.top-s.base);
}


int main()
{
    sqstack s;
    initstack(&s);
    char c;
    int i=0;
    double d,e;
    printf("请按逆波兰表达式计算待输入数据,数据与运算符之间用空格隔开,以#结束\n");
    scanf("%c",&c);
    char str[100];
    while(c!='#')
    {
        while(isdigit(c) ||c=='.')//用于过滤数字
        {
            str[i++]=c;
            str[i]='\0';// 必须加上;
            if(i>=10)
            {
                printf("数据过大");
                return -1;
            }
            scanf("%c",&c);
            if(c==' ')
            {
                d=atof(str);//转换为浮点数--atod转换为整形
                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("除数为0,有错");
                return -1;
            }
            break;

        }
        scanf("%c",&c);
    }
    pop(&s,&d);
    printf("结果为:%lf\n",d);
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
linux协议学习涉及到网络协议的实现和内核源码的理解。在linux内核中,网络协议是由一系列网络协议层组成的,包括物理层、数据链路层、网络层、传输层和应用层。每个层次都有相应的协议和功能。 在内核网络子系统初始化时,L4层协议(如TCP和UDP)会被注册,通过注册的协议,内核可以分发接收到的网络数据包。例如,TCP协议的注册包括对应的处理函数tcp_v4_rcv,UDP协议的注册包括对应的处理函数udp_rcv。这些处理函数负责解析和处理接收到的数据包。 在linux协议学习中,了解如何添加自定义协议也是非常重要的。以INET协议簇为例,可以使用函数inet_add_protocol来注册自定义的网络协议。该函数需要传入一个指向net_protocol结构的指针和协议号。 为了深入学习linux协议,你可以通过以下几个途径进行: 1. 阅读内核源码:深入研究内核源码是学习linux协议的最佳途径。可以从网络协议的初始化、协议处理函数等方面入手,逐步理解各个层次的实现。 2. 参考相关书籍和教程:有很多书籍和在线教程专门介绍linux协议的实现和原理。这些资料可以帮助你更好地理解协议的工作原理和实现细节。 3. 参与开源项目:参与开源项目可以提供实践的机会,可以通过参与网络协议的开发来加深对linux协议的理解。 4. 加入开发交流群:加入开发交流群可以与其他开发者讨论和交流,获取更多的学习资源和经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值