news 2026/4/27 15:55:16

栈和队列的应用---表达式求值,递归(C语言知识)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
栈和队列的应用---表达式求值,递归(C语言知识)

表达式求值

中缀表达式后缀表达式
5+6*3563*+
b*c/dbc*c/
(5+6)*756+7*
x/y- z+i*j–x *yxy/z-ij*+xy *-
x*y-6xy*6-

枚举

将变量的值一一列举出来,变量的值只限于列举出来的值的范围内

在枚举中列出的每一个值,成为枚举元素

每一个枚举元素由系统定义了一个用序号表示的数值,从0开始,分别为0,1,2,······

语法:

enum枚举名{枚举元素....};
#include<stdio.h>typedefenum{mon=1,tue,wed,thu,fri,sat,sum}weekday;enumbool{false,ture};intmain(){enumweekdaya;a=mon;enumweekdayb;b=tue;printf("%d\n",a);//1printf("%d\n",b);//2return0;}

后缀表达式求值

  1. 从左到右遍历后缀表达式的每个元素:
    • 若元素是操作数,直接压入栈中。
    • 若元素是运算符,弹出栈顶的2 个操作数(注意顺序:后弹出的是左操作数,先弹出的是右操作数),用运算符计算后,将结果压回栈中。
  2. 遍历结束后,栈中剩余的唯一元素就是表达式的计算结果。

#include<stdio.h>#include<stdlib.h>#defineMAXSIZE100typedefintElemType;typedefstruct{ElemType*data;inttop;}Stack;typedefenum{LEFT_PARE,RIGHT_PARE,//左括号,右括号ADD,SUB,MUL,DIV,MOD,// 加,减,乘,除,取余EOS,NUM// \0,数字}contentType;charexpr[]="82/2+56*-";//初始化Stack*initStack(){Stack*s=(Stack*)malloc(sizeof(Stack));s->data=(ElemType*)malloc(sizeof(ElemType));s->top=-1;returns;}// 判断栈是否为空intisEmpty(Stack*s){if(s->top==-1){printf("空的\n");return1;}else{return0;}}//进栈intpush(Stack*s,ElemType e){if(s->top>=MAXSIZE-1){printf("满了\n");return0;}s->top++;s->data[s->top]=e;return1;}//出栈ElemTypepop(Stack*s,ElemType*e){if(s->top==-1){printf("空的\n");return0;}*e=s->data[s->top];s->top--;return1;}// 获取栈顶元素intgetTop(Stack*s,ElemType*e){if(s->top==-1){printf("空的\n");return0;}*e=s->data[s->top];return1;}contentTypegetToken(char*symbol,int*index){*symbol=expr[*index];*index=*index+1;switch(*symbol){case'(':returnLEFT_PARE;case')':returnRIGHT_PARE;case'+':returnADD;case'-':returnSUB;case'*':returnMUL;case'/':returnDIV;case'%':returnMOD;case'\0':returnEOS;default:returnNUM;}}inteval(Stack*s){charsymbol;intop1,op2;intindex=0;contentType token;token=getToken(&symbol,&index);ElemType result;while(token!=EOS){if(token==NUM){push(s,symbol-'0');// symbol - '0'得到数值}else{//op2是栈顶,op1是次顶pop(s,&op2);pop(s,&op1);switch(token){caseADD:push(s,op1+op2);break;caseSUB:push(s,op1-op2);break;caseMUL:push(s,op1*op2);break;caseDIV:if(op2==0){printf("错误:除数不能为0!\n");return0;}push(s,op1/op2);break;caseMOD:if(op2==0){printf("错误:模运算除数不能为0!\n");return0;}push(s,op1%op2);break;default:printf("未知运算符!\n");break;}}// 获取下一个tokentoken=getToken(&symbol,&index);}pop(s,&result);printf("%d\n",result);//结果:-24return1;}intmain(){Stack*s=initStack();eval(s);return0;}

中缀表达式转后缀表达式

x/(i-j)*y———>xij-/y*

1. 优先级定义(从高到低)
运算符优先级说明
(0左括号入栈时优先级最低
+-1加减
*/%2乘除、取模
)-右括号仅用于匹配左括号
2. 转换步骤
  1. 初始化:空栈(存储运算符) + 空输出队列(存储后缀表达式);

  2. 遍历中缀表达式的每个 token

    (数字 / 运算符 / 括号):

    • 若为数字:直接加入输出队列;
    • 若为左括号(:压入栈;
    • 若为右括号):持续弹出栈顶运算符到输出队列,直到遇到左括号(,并弹出左括号(不加入输出);
    • 若为运算符:
      • 栈非空时,持续弹出栈顶优先级 ≥ 当前运算符的运算符到输出队列;
      • 将当前运算符压入栈;
  3. 遍历结束后:将栈中剩余的所有运算符依次弹出到输出队列;

  4. 输出队列即为后缀表达式。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<ctype.h>#defineMAXSIZE100typedefintElemType;typedefstruct{ElemType*data;inttop;}Stack;typedefenum{LEFT_PARE,// 0RIGHT_PARE,// 1ADD,// 2SUB,// 3MUL,// 4DIV,// 5MOD,// 6EOS,// 7NUM// 8}contentType;charexpr[]="x/(i-j)*y";//char expr[] = "8/(5-3)*4"; // 中缀表达式charpostfix_expr[MAXSIZE]={0};// 存储后缀表达式(字符形式,如'+'而非枚举值)intpostfix_idx=0;// 修正后的优先级数组intin_stack[]={0,19,12,12,13,13,13,0,0};intout_stack[]={19,0,12,12,13,13,13,0,0};// 枚举值转运算符字符chartoken_to_char(contentType token){switch(token){caseADD:return'+';caseSUB:return'-';caseMUL:return'*';caseDIV:return'/';caseMOD:return'%';default:return'\0';}}// 字符转枚举值contentTypechar_to_token(charc){switch(c){case'+':returnADD;case'-':returnSUB;case'*':returnMUL;case'/':returnDIV;case'%':returnMOD;case'(':returnLEFT_PARE;case')':returnRIGHT_PARE;case'\0':returnEOS;default:returnNUM;}}//初始化栈Stack*initStack(){Stack*s=(Stack*)malloc(sizeof(Stack));s->data=(ElemType*)malloc(MAXSIZE*sizeof(ElemType));s->top=-1;returns;}// 判断栈是否为空intisEmpty(Stack*s){returns->top==-1;}//进栈intpush(Stack*s,ElemType e){if(s->top>=MAXSIZE-1)return0;s->top++;s->data[s->top]=e;return1;}//出栈intpop(Stack*s,ElemType*e){if(isEmpty(s))return0;*e=s->data[s->top];s->top--;return1;}// 获取栈顶元素intgetTop(Stack*s,ElemType*e){if(isEmpty(s))return0;*e=s->data[s->top];return1;}// 释放栈内存voidfreeStack(Stack*s){if(s){free(s->data);free(s);}}// 获取TokencontentTypegetToken(char*symbol,int*index){*symbol=expr[*index];if(*symbol=='\0')returnEOS;*index=*index+1;returnchar_to_token(*symbol);}// 打印Tokenvoidprint_token(contentType token,charsymbol){switch(token){caseADD:printf("+");break;caseSUB:printf("-");break;caseMUL:printf("*");break;caseDIV:printf("/");break;caseMOD:printf("%%");break;caseNUM:printf("%c",symbol);break;default:break;}}// 中缀转后缀voidpostfix(Stack*s){contentType token;intindex=0;charsymbol;ElemType e;postfix_idx=0;memset(postfix_expr,0,sizeof(postfix_expr));push(s,EOS);token=getToken(&symbol,&index);while(token!=EOS){if(token==NUM){print_token(token,symbol);postfix_expr[postfix_idx++]=symbol;// 存储数字字符}elseif(token==RIGHT_PARE){getTop(s,&e);while(e!=LEFT_PARE){if(!pop(s,&e))break;if(e==LEFT_PARE)break;charop=token_to_char((contentType)e);print_token((contentType)e,op);postfix_expr[postfix_idx++]=op;// 存储运算符字符getTop(s,&e);}pop(s,&e);}elseif(token==LEFT_PARE){push(s,token);}else{getTop(s,&e);while(in_stack[e]>=out_stack[token]){if(!pop(s,&e))break;charop=token_to_char((contentType)e);print_token((contentType)e,op);postfix_expr[postfix_idx++]=op;// 存储运算符字符getTop(s,&e);}push(s,token);}token=getToken(&symbol,&index);}// 弹出剩余运算符getTop(s,&e);while(e!=EOS){pop(s,&e);charop=token_to_char((contentType)e);if(op!='\0'){// 过滤无效字符print_token((contentType)e,op);postfix_expr[postfix_idx++]=op;}getTop(s,&e);}printf("\n");}// 后缀表达式求值inteval(Stack*s,char*post_expr){intindex=0;ElemType result,op1,op2;s->top=-1;// 重置栈while(post_expr[index]!='\0'){charc=post_expr[index];index++;if(isdigit(c)){// 数字入栈push(s,c-'0');}elseif(c=='+'||c=='-'||c=='*'||c=='/'||c=='%'){// 运算符计算if(!pop(s,&op2)||!pop(s,&op1)){printf("操作数不足!\n");return0;}switch(c){case'+':push(s,op1+op2);break;case'-':push(s,op1-op2);break;case'*':push(s,op1*op2);break;case'/':if(op2==0){printf("除数不能为0!\n");return0;}push(s,op1/op2);break;case'%':if(op2==0){printf("模运算除数不能为0!\n");return0;}push(s,op1%op2);break;}}}// 弹出最终结果if(pop(s,&result)&&isEmpty(s)){printf("求值结果:%d\n",result);return1;}else{printf("表达式格式错误!\n");return0;}}intmain(){Stack*s=initStack();// 1. 中缀转后缀printf("中缀表达式:%s\n",expr);printf("后缀表达式:");postfix(s);// 2. 后缀表达式求值if(strspn(expr,"0123456789+-*/%()")==strlen(expr)){eval(s,postfix_expr);}else{printf("表达式含字母,跳过求值!\n");}freeStack(s);return0;}

中缀表达式:x/(i-j)*y
后缀表达式:xij-/y *
表达式含字母,跳过求值!

递归

在函数调用过程中,调用自己本身

计算1~n的和

非递归方式

intfun(intn){intsum=0;for(inti=0;i<n;i++){sum=sum+i;}returnsum;}

递归方式

intfun(intn){if(n==1){return1;}else{returnfun(n-1)+n;}}

斐波那契数列

斐波那契数列,又称黄金分割数列,其数值为:1、1、2、3、5、8、13、21、34······

非递归

intfib(intn){inta=1;intb=1;intresult=1;while(n>2){result=a+b;a=b;b=result;n--;}returnresult;}intmain(){intn;scanf("%d",&n);intret=fib(n);printf("%d\n",ret);reurn0;}

递归

intfib(intn){if(n<=2){return1;}else{returnfib(n-1)+fib(n-2);}}intmain(){intn;scanf("%d",&n);intret=fib(n);printf("%d",ret);return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/25 7:37:47

MMSA框架:多模态情感分析的终极指南与实战应用

MMSA框架&#xff1a;多模态情感分析的终极指南与实战应用 【免费下载链接】MMSA MMSA is a unified framework for Multimodal Sentiment Analysis. 项目地址: https://gitcode.com/gh_mirrors/mm/MMSA 在人工智能快速发展的今天&#xff0c;多模态情感分析正成为理解人…

作者头像 李华
网站建设 2026/4/23 2:09:20

Markdowner:网站内容秒变AI友好Markdown的终极神器

还在为网站内容整理发愁吗&#xff1f;Markdowner来帮你&#xff01;这个强大的开源工具能够将任何网站瞬间转换为适合大型语言模型处理的Markdown格式数据&#xff0c;让你的AI应用更智能、更高效。 【免费下载链接】markdowner A fast tool to convert any website into LLM-…

作者头像 李华
网站建设 2026/4/23 13:15:17

如何扛住《珠江》所有拍摄考验?幕后8K设备实力揭晓

珠江&#xff0c;一条承载着千年商贸与人文记忆的水道&#xff0c;其纪录片拍摄始终面临着独特挑战——变幻的光线、复杂的水汽环境、需要同时捕捉的宏大场景与精微细节。当拍摄团队决定采用博冠8K摄像机完成这一项目时&#xff0c;这既是对设备性能的一次高强度检验&#xff0…

作者头像 李华
网站建设 2026/4/23 14:22:47

41、网络与文件权限及数字系统知识详解

网络与文件权限及数字系统知识详解 一、网络文件权限相关 特定用户权限分析 对于Roger,他是Everyone、Executive和Marketing组的成员,可依据相关图表和表格,在项目日志中明确其组合权限和有效权限。 对于Susan,作为Everyone、Accounting、Executive和Finance组的成员,…

作者头像 李华
网站建设 2026/4/18 9:39:28

Heimdallr浏览器扩展:终极安全监控工具使用指南

Heimdallr是一款专为安全研究人员设计的Chrome浏览器扩展&#xff0c;致力于被动嗅探浏览器流量&#xff0c;提供漏洞框架指纹识别、蜜罐请求告警拦截以及浏览器特征追踪对抗等功能。本指南将详细介绍如何安装和使用这款强大的安全监控工具。 【免费下载链接】Heimdallr 项目…

作者头像 李华
网站建设 2026/4/23 0:54:10

5分钟快速上手Skipper API网关:微服务路由终极指南

5分钟快速上手Skipper API网关&#xff1a;微服务路由终极指南 【免费下载链接】skipper An HTTP router and reverse proxy for service composition, including use cases like Kubernetes Ingress 项目地址: https://gitcode.com/gh_mirrors/sk/skipper Skipper是一个…

作者头像 李华