热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c语言利用栈实现表达式求值_数据结构:栈的数制转换与表达式求值,最容易错的计算

只要问题满足“后进先出”的特点,都可以使用栈来解决。数制转换和表达式求值是栈的典型应用,结合视频理解其算法原理和算法步骤。1.数制转换数值进位制的换算是

只要问题满足“后进先出”的特点,都可以使用栈来解决。数制转换和表达式求值是栈的典型应用,结合视频理解其算法原理和算法步骤。

1.数制转换

数值进位制的换算是计算机实现计算和处理的基本问题。比如将十进制数m转换为n进制的数,最常用的算法是除n取余法。这种方法是将十进制数m每次除以n,直到商为0时为止。将所得的余数依次进栈,然后按“后进先出”的次序出栈便得到转换结果。其基本原理是:

m=(m / n)* n + m % n ( 其中: / 为整除,%为求余 )

将十进制数1567转换为八进制数。

设m=1567 ,n=8。按照除8取余法,转换方法和结果如下:

37ad497914c922c3d4cc57200cb1c50c.png

按照上述除8取余法,得到的余数依次是7,3,0,3。在转换过程中每得到一个余数则进栈保存,最先得到的余数7在栈底,最后得到的余数3在栈顶,转换完毕后依次出栈,其输出顺序与计算顺序正好相反,为3、0、3、7。数值3037即为转换后的八进制数,可表示为:

(1567)10 =(3037)8

将十进制数转换为n进制数的过程中,计算顺序与输出顺序正好相反。因此,利用栈解决这个问题是很合适的。

算法原理:

(1)逐次计算得到相关结果,先计算得到的结果后输出;

(2)把逐次得的余数依次进栈,计算结束后依次出栈。

算法要点(采用顺序栈):

(1)m!=0 ,m%n 的余数进栈;

若m==0,结束求余运算,依次进行出栈操作;

(2)m=m/n;

(3)重复(1)和(2)。

利用顺序栈将任意的十进制非负整数转换为等价的n进制数输出的完整程序如下 :

#include#include#define MaxSize 100 /*定义顺序栈所能存储的最多的元素的个数*/typedef int ElemType; /*数据元素类型一般用ElemType表示*/struct SeqStack{ /*顺序栈的类型定义*/  ElemType data[MaxSize]; /*用data数组存储栈中所有的数据元素*/  int top; /*用整型变量top指示栈顶元素的位置*/};#include "顺序栈基本操作.c" /*顺序栈的6种运算包含在此文件中*/void transform(int m, int n) /*将一个十进制整数m转换为n进制数输出函数*/{int k; /*用来保存余数*/  int mm=m; /*用来保存被转换的十进制数m*/   struct SeqStack S; /*顺序栈的变量定义*/  InitStack(&S); /*将顺序栈a初始化*/  while(m!=0) {   k=m%n; /*将十进制数m除以n进制数的余数存入k*/   Push(&S,k); /*将k的值进栈a中*/   m=m/n; /*用m除以n的整数商又赋给m*/  }  printf("十进制数 %d 转换为 %d 进制数为:",mm,n);  while(!StackEmpty(&S)) { /*元素依次出栈 */   k=Pop(&S,k);   printf("%d",k);  }  printf("");}/*transform end*/ void main(){  printf("将十进制数转换为任意进制数实例:");  transform(1567,8); /*将十进制数转换为八进制数 */  transform(1567,6); /*将十进制数转换为六进制数 */  transform(1567,4); /*将十进制数转换为四进制数 */  transform(1567,2); /*将十进制数转换为二进制数 */}

上机运行该程序后,得到的运行结果如下:

将十进制数转换为任意进制数实例:

十进制数 1567 转换为 8 进制数为:3037

十进制数 1567 转换为 6 进制数为:11131

十进制数 1567 转换为 4 进制数为:120133

十进制数 1567 转换为 2 进制数为:11000011111

2.表达式的求值

后缀表达式的求值比较简单,扫描一遍即可完成。具体做法是:设置一个栈,开始时栈为空,当从左到右扫描表达式时,若遇到操作数,则进栈,若遇到运算符,则从栈中退出两个操作数,先退出的放在运算符的右边,后退出的放在运算符的左边,然后将运算后的结果再进栈,直到整个表达式结束。此时,栈中只有一个元素,该元素即为运算结果。

求后缀表达式12 3 20 4/ * 8-6 * +的值。

栈的变化情况如表3-1所示:

表3-1 后缀表达式求值时栈的变化

f1cbdc143232a179ffe2516ae6d2022c.png

【算法3-12】 后缀表达式的求值算法int Compute(char * str) /*计算由str所指字符串的后缀表达式的值*/{ /*用顺序栈S存储操作数和中间计算结果&#xff0c;元素类型为int*/  struct SeqStack S; /*定义x用于保存操作数&#xff0c;定义i用于扫描后缀表达式*/  int x;  int i&#61;0;  InitStack(&S); /*初始化栈S&#xff0c;预分配5个浮点数空间&#xff0c;以后自动增长*/  while(str[i]) { /*扫描后缀表达式中的每个字符&#xff0c;并进行相应处理*/   if(str[i]&#61;&#61;&#39; &#39;) {i&#43;&#43;; continue;} /*扫描到空格字符不做任何处理*/   switch(str[i])   {    case &#39;&#43;&#39;: /*做栈顶两个元素的加法&#xff0c;和赋给x*/     x&#61;Pop(&s)&#43;Pop(&S);     i&#43;&#43;; break;    case &#39;-&#39;: /*做栈顶两个元素的减法&#xff0c;差赋给x*/     x&#61;Pop(&S); /*弹出减数*/     x&#61;Pop(&S)-x; /*弹出被减数并做减法*/     i&#43;&#43;; break;    case &#39;*&#39;: /*做栈顶两个元素的乘法&#xff0c;积赋给x*/     x&#61;Pop(&S)*Pop(&S);     i&#43;&#43;; break;    case &#39;/&#39;: /*做栈顶两个元素的除法&#xff0c;商赋给x*/     x&#61;Pop(&S); /*弹出除数*/     if(x!&#61;0.0)       x&#61;Pop(&S)/x; /*弹出被除数并做除法*/     else { /*除数为0时终止运行*/       printf("除数为0!");       exit(1);     }     i&#43;&#43;; break;    default: /*扫描到的是整数字符串&#xff0c;生成对应的整数*/     x&#61;0; /*利用x保存扫描到的整数*/     while(str[i]>&#61;48 && str[i]<&#61;57) {       x&#61;x*10&#43;str[i]-48; i&#43;&#43;;    }  }  Push(&S,x);   /*把扫描转换后或进行相应运算后得到的整数压入栈S中*/ } /*while end*/if(StackEmpty(&S)) { /*若计算结束后栈为空则中止运行*/   printf("后缀表达式格式错!");  exit(1);}/*若栈中仅有一个元素&#xff0c;则它就是后缀表达式的值&#xff0c;否则为出错*/x&#61;Pop(&S);if(StackEmpty(&S)) return x; else {  printf("后缀表达式格式错!");  exit(1); }}



推荐阅读
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了C函数ispunct()的用法及示例代码。ispunct()函数用于检查传递的字符是否是标点符号,如果是标点符号则返回非零值,否则返回零。示例代码演示了如何使用ispunct()函数来判断字符是否为标点符号。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
author-avatar
木头人2幸福
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有