C语言数据结构之中缀树转后缀树的实例
发布时间 - 2026-01-11 02:59:57 点击率:次C语言数据结构之中缀树转后缀树的实例

对于一个中缀表达式 a+b*c*(d-e/f) 转换成后缀是这样的形式 abc*def/-+
后缀表达式是相当有用处的,转换成后缀表达式后求值会简单很多.那么该如何转换呢?
网上关于这方面的资料一搜一大把,每本数据结构的书中都会提及这个算法,在这个算法中,用到 栈 这个数据结构.
1,关键是比较运算符的优先级,谁的优先级高,谁就出现在前面上面的表达式中,有括号的时候括号优先级最高,*/次之,+-最后. 在上面的表达式中+的优先级不如*的高,因此,在后缀表达式中*出现在+前面,
2,遇到操作数的时候总是直接输出,不做任何比较
3,遇到左括号总是直接入栈,遇到右括号的时候总是弹栈,一直弹到遇到一个左括号
4,遇到操作符的时候就先将这个操作符和它前面的操作符比较优先级,假如高于前面的优先级,先将它压栈,假如低于或等于前面的操作符的优先级,就把前面的优先级比它高的或相等的顺序弹出来, 一直弹到遇到优先级比它还低的或者到了栈顶 ,然后该操作符再压入栈。
知道以上四个规则就可以设计代码实现了,
代码如下:
#include<iostream>
#include<string>
#include<stack>
#include<map>
using namespace std;
void InerStringDevide(string InerStr,string DeviStr[],int &num)
{
int count,i;
int numbe=InerStr.size();
for(i=0;i<numbe;i++)
DeviStr[i][0]='\0';
count=0;
for(i=0;i<numbe;)
{
if(InerStr[i]=='+'||InerStr[i]=='-'||InerStr[i]=='*'||
InerStr[i]=='/'||InerStr[i]=='%'||InerStr[i]=='^'
||InerStr[i]=='('||InerStr[i]==')')
{
DeviStr[count].push_back(InerStr[i]);
count++;
i++;
}
else
{
while(InerStr[i]!='+'&&InerStr[i]!='-'&&InerStr[i]!='*'&&
InerStr[i]!='/'&&InerStr[i]!='%'&&InerStr[i]!='^'
&&InerStr[i]!='('&&InerStr[i]!=')')
{
DeviStr[count].push_back(InerStr[i]);
i++;
if(i>=numbe)
break;
}
count++;
}
}
num=count;
}
void InerTreeToPostTree(string InerStr,string &PostStr)
{
PostStr[0]='\0';
map<char,int>OpC;
typedef map<char,int>::value_type ValType;
OpC.insert(ValType('+',1));
OpC.insert(ValType('-',1));
OpC.insert(ValType('*',2));
OpC.insert(ValType('/',2));
OpC.insert(ValType('%',2));
OpC.insert(ValType('^',3));
OpC.insert(ValType('(',-1));
OpC.insert(ValType(')',0));
int num,i,j,StrNum;
num=InerStr.size();
string *DevedeStr=new string[num];
InerStringDevide(InerStr,DevedeStr,StrNum);
stack<char> ChStack;
int count=0;
for(int i=0;i<StrNum;i++)
{
//如果输入的字符串是操作符
if(DevedeStr[i][0]=='+'||DevedeStr[i][0]=='-'||DevedeStr[i][0]=='*'||
DevedeStr[i][0]=='/'||DevedeStr[i][0]=='%'||DevedeStr[i][0]=='^'
||DevedeStr[i][0]=='('||DevedeStr[i][0]==')')
{
//如果操作符栈中为空可以直接将操作符入栈
if(ChStack.empty())
{
ChStack.push(DevedeStr[i][0]);
}
//如果非空要根据操作符的优先级及其类别进行判断并分类入栈
else
{
char TopCh=ChStack.top();
//如果是(则直接入栈
if(OpC[DevedeStr[i][0]]==-1)
{
ChStack.push(DevedeStr[i][0]);
}
//如果操作符优先级大于栈中当前操作符直接入栈
else if(OpC[TopCh]<OpC[DevedeStr[i][0]])
{
ChStack.push(DevedeStr[i][0]);
}
//否则按操作符的类别有区别的处理
else
{
//如果遇到)则操作符出栈并入字符串
if(OpC[DevedeStr[i][0]]==0)
{
TopCh=ChStack.top();
while(OpC[TopCh]!=-1)
{
if(!PostStr.empty())
{
PostStr.push_back(' ');
}
PostStr.push_back(TopCh);
ChStack.pop();
TopCh=ChStack.top();
}
ChStack.pop();
TopCh=ChStack.top();
}
else
{
while(OpC[TopCh]>=OpC[DevedeStr[i][0]]&&OpC[TopCh]!=-1)
{
if(!PostStr.empty())
{
PostStr.push_back(' ');
}
PostStr.push_back(TopCh);
ChStack.pop();
if(!ChStack.empty())
TopCh=ChStack.top();
else
break;
}
ChStack.push(DevedeStr[i][0]);
}
}
}
}
//如果输入的字符串是数字
else
{
int DevideSize=DevedeStr[i].size();
if(!PostStr.empty())
{
PostStr.push_back(' ');
}
for(int j=0;j<DevideSize;j++)
{
PostStr.push_back(DevedeStr[i][j]);
}
}
}
while(!ChStack.empty())
{
if(!PostStr.empty())
{
PostStr.push_back(' ');
}
PostStr.push_back(ChStack.top());
ChStack.pop();
}
}
以上为头文件InerTreeToPostTree.h。该文件的 作用是输入中缀字符串,输出后缀字符串,其中中缀字符串不带空格,而后缀字符串带空格。头文件中的另一个函数是将字符串分为字符串数组,该数组中存储数字和运算符。
#include<iostream>
#include<stack>
#include<string>
using namespace std;
void StringDevide(string str,int &num,string st1[])
{
for(int i=0;i<100;i++)
st1[i][0]='\0';
int n=str.size();
int j=0,count=0;
for(int i=0;i<n;i++)
{
if(str[i]!=' ')
{
st1[count].push_back(str[i]);
}
else
{
count++;
}
}
num=count+1;
}
void StringToNum(string str,int &num)
{
num=0;
int n=str.size();
for(int i=0;i<n;i++)
{
num=num*10;
num+=str[i]-'0';
}
}
class InterTreeComputer
{
private:
//要计算的表达式
string m_expresion;
//将数字存储到栈中
stack<int> m_num;
public:
InterTreeComputer(string expression):m_expresion(expression)
{}
//判定某一操作符是否是运算符
bool IsOperator(char ch)const;
//获取要计算的两个运算数
void GetOperands(int &left,int &right);
//对获取的两个数按照符号ch进行计算
int computer(int left,int right,char ch)const;
//获取表达式
string GetPostoperation()const;
void SetPostoperator();
//计算表达式并返回结果
int Evaluate();
};
bool InterTreeComputer::IsOperator(char ch)const
{
switch(ch)
{
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
return 1;
default:
return 0;
}
}
void InterTreeComputer::GetOperands(int &left,int &right)
{
if(m_num.empty())
{
cout<<"num stack is empty!";
return ;
}
right=m_num.top();
m_num.pop();
if(m_num.empty())
{
cout<<"the expression is wrong!"<<endl;
return ;
}
left=m_num.top();
m_num.pop();
}
int InterTreeComputer::computer(int left,int right,char ch)const
{
switch(ch)
{
case '+':
return left+right;
break;
case '-':
return left-right;
break;
case '*':
return left*right;
break;
case '/':
if(right==0)
{
cout<<"the expression is wrong"<<endl;
return -1;
}
return left/right;
break;
case '%':
return left%right;
break;
case '^':
if(left==0&&right==0)
{
cout<<"the expression is wrong"<<endl;
return -1;
}
int value=1;
while(right>0)
{
value*=left;
right--;
}
return value;
break;
}
}
string InterTreeComputer::GetPostoperation()const
{
return m_expresion;
}
void InterTreeComputer::SetPostoperator()
{}
int InterTreeComputer::Evaluate()
{
string *str=new string[100];
int num;
StringDevide(m_expresion,num,str);
for(int i=0;i<num;i++)
{
if(str[i][0]=='+'||str[i][0]=='-'||str[i][0]=='*'||str[i][0]=='/'
||str[i][0]=='%'||str[i][0]=='^')
{
char ch=str[i][0];
int left,right;
GetOperands(left,right);
int number=computer(left,right,ch);
m_num.push(number);
}
else
{
int numb=0;
StringToNum(str[i],numb);
m_num.push(numb);
}
}
return m_num.top();
}
以上代码为InerTreeComputer.h头文件,该头文件的作用是输入后缀表达式并计算该表达式的值。
#include<iostream>
using namespace std;
#include<string>
#include<stack>
#include"InterTreeComputer.h"
#include"InerTreeToPostTree.h"
int main()
{
string str="3*(4-2^5)+6";
string st1="2 3 ^ 1 +";
string st2="2 2 3 ^ ^ 4 /";
string StrRe;
InerTreeToPostTree(str,StrRe);
InterTreeComputer Comp(StrRe);
cout<<Comp.GetPostoperation()<<endl;
cout<<Comp.Evaluate()<<endl;
return 0;
}
测试文件对以上两个头文件进行了测试。
以上就是数据结构C语言数据结构之中缀树转后缀树的实例,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持,大家共同进步!
# C语言数据结构之中缀树转后缀树
# 数据结构
# 中缀树转后缀树
# C语言数据结构实现银行模拟
# C语言数据结构旋转链表的实现
# C语言数据结构 快速排序实例详解
# C语言数据结构实现链表去重的实例
# C语言 数据结构链表的实例(十九种操作)
# C语言数据结构之栈简单操作
# C语言数据结构之双向循环链表的实例
# C语言数据结构之循环链表的简单实例
# C语言数据结构算法之实现快速傅立叶变换
# C语言中数据结构之链式基数排序
# 头文件
# 出现在
# 运算符
# 直接入
# 转换成
# 在这个
# 是这样
# 如有
# 就把
# 希望能
# 弹出
# 可以直接
# 不做
# 该如何
# 书中
# 在上面
# 谁的
# 将它
# 谢谢大家
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
JavaScript中如何操作剪贴板_ClipboardAPI怎么用
百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏
简单实现jsp分页
JS实现鼠标移上去显示图片或微信二维码
如何快速生成橙子建站落地页链接?
Laravel怎么使用Markdown渲染文档_Laravel将Markdown内容转HTML页面展示【实战】
网站制作免费,什么网站能看正片电影?
WEB开发之注册页面验证码倒计时代码的实现
Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】
Python高阶函数应用_函数作为参数说明【指导】
QQ浏览器网页版登录入口 个人中心在线进入
公司网站制作价格怎么算,公司办个官网需要多少钱?
如何使用 jQuery 正确渲染 Instagram 风格的标签列表
如何安全更换建站之星模板并保留数据?
网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?
JavaScript如何实现继承_有哪些常用方法
佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】
Laravel如何创建自定义Facades?(详细步骤)
Android自定义listview布局实现上拉加载下拉刷新功能
绝密ChatGPT指令:手把手教你生成HR无法拒绝的求职信
Windows10电脑怎么设置虚拟光驱_Win10右键装载ISO镜像文件
如何用JavaScript实现文本编辑器_光标和选区怎么处理
如何为不同团队 ID 动态生成多个独立按钮
html5的keygen标签为什么废弃_替代方案说明【解答】
如何用AWS免费套餐快速搭建高效网站?
如何做网站制作流程,*游戏网站怎么搭建?
Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】
智能起名网站制作软件有哪些,制作logo的软件?
Laravel PHP版本要求一览_Laravel各版本环境要求对照
IOS倒计时设置UIButton标题title的抖动问题
Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)
Laravel如何实现API版本控制_Laravel版本化API设计方案
Laravel如何使用Telescope进行调试?(安装和使用教程)
html文件怎么打开证书错误_https协议的html打开提示不安全【指南】
网站视频制作书签怎么做,ie浏览器怎么将网站固定在书签工具栏?
如何生成腾讯云建站专用兑换码?
Bootstrap整体框架之CSS12栅格系统
Android中AutoCompleteTextView自动提示
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】
瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口
如何在局域网内绑定自建网站域名?
如何在Windows环境下新建FTP站点并设置权限?
宙斯浏览器文件分类查看教程 快速筛选视频文档与图片方法
Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
详解阿里云nginx服务器多站点的配置
Laravel定时任务怎么设置_Laravel Crontab调度器配置
厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?
php 三元运算符实例详细介绍

