P1175 表达式的转换 (栈 链表

该博客主要介绍了如何实现逆波兰表达式的计算,包括将中缀表达式转换为后缀表达式的方法,并提供了具体的C++代码实现。文章通过`tosuffix`函数展示了从中缀到后缀的转换过程,然后利用`calc`函数进行计算。博客内容涵盖了括号处理、运算符优先级以及计算逻辑。

添加链接描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define MAXN 100005
#define MAXM 1000005
int priority(const char &ch){
	switch(ch){
		case '+':
		case '-':
			return 1;
		case '*':
		case '/':
			return 2;
		case '^':
			return 3;
		default :
			return 0;
	}
	
}
string tosuffix(const string &s){//
	string ret;
	stack<char>st;
	for(int i=0;i<s.size();i++){
		if(isdigit(s[i])){
			ret+=s[i];
		}
		else if(s[i]=='(')st.push(s[i]);
		else if(s[i]==')'){
			while(st.top()!='('){
				//TODO
				ret+=st.top();
				st.pop();
			}
			st.pop();
		}
		else {
			while(!st.empty()&&priority(st.top())>=priority(s[i])){
				ret+=st.top(),st.pop();
				
			}
			st.push(s[i]);
		}
		
	}
	while(!st.empty()){
		ret+=st.top(),st.pop();
	}
	return ret;
}
int calcNUM( int &a, int &b,const int & symbol){
	switch (symbol) {
		case '+':
			//TODO
			return a+b;
		case '-':
			//TODO
			return a-b;
		case '*':
			return a*b;
		case '/':
			return a/b;
		case '^':
			return (int)pow(a,b);
		default:
			//TODO
			return 0;
	}
}
void print_(const string &s){
	for(int i=0;i<s.size();i++){
		cout<<s[i]<<" ";
	}
	cout<<endl;
}
void calc (const string &s){
	list<int>st;
	print_(s);
	for(int i=0;i<s.size();i++){
		if(isdigit(s[i])){
			st.push_back(s[i]-'0');
		}
		else {
			int a,b;
			a=st.back();
			st.pop_back();
			b=st.back();
			st.pop_back();
			st.push_back(calcNUM(b,a,s[i]));
			for(list<int>::iterator it =st.begin();it!=st.end();it++)
				cout<<*it<<" ";//
			
			for(int j=i+1;j<s.size();j++){
				cout<<s[j]<<" ";
			}
			cout<<endl;
			
		}
	}
}
int main(){
	string s;
	cin>>s;
	calc(tosuffix(s));

    return 0;
}



### C语言链式实现中缀表达式转换为后缀表达式 #### 使用链式结构定义 为了实现这一功能,首先需要定义一个链式的数据结构。这可以通过创建节点来完成,每个节点存储一个字符以及指向下一个节点的指针。 ```c typedef struct StackNode { char data; struct StackNode *next; } StackNode; typedef struct { StackNode *top; // 顶指针 } LinkStack; ``` 初始化一个新的空: ```c void InitStack(LinkStack *S) { S->top = NULL; } ``` 向中压入新元素的方法如下所示[^1]: ```c bool Push(LinkStack *S, char e) { StackNode *p = (StackNode *)malloc(sizeof(StackNode)); p->data = e; p->next = S->top; S->top = p; return true; } ``` 从中弹出最上面的一个元素,并返回其值: ```c char Pop(LinkStack *S) { if (!IsEmpty(S)) { // 判断是否为空 StackNode *temp = S->top; char res = temp->data; S->top = temp->next; free(temp); return res; } printf("Error: stack is empty\n"); exit(-1); // 如果尝试从空弹出,则报错退出程序 } ``` 判断当前是否为空: ```c bool IsEmpty(LinkStack *S) { return S->top == NULL; } ``` 获取顶元素而不移除它: ```c char GetTop(LinkStack *S) { if (!IsEmpty(S)) return S->top->data; else { printf("Error: stack is empty\n"); exit(-1); } } ``` #### 中缀转后缀的核心算法逻辑 对于给定的字符串形式的算术表达式,按照以下规则处理每一个字符直到遍历结束: - 数字直接加入输出队列; - 左括号`(`立即推入内; - 右括号`)`会触发将内的运算符持续推出至遇到对应的左括号为止(注意:此时应丢弃这对匹配的括号),而不会把它们放入最终的结果序列里; - 当前扫描到的是运算符时(假设为op),则需考虑先比较优先级再决定动作——如果顶的操作符具有更高的或相等的优先级别于op的话就将其弹出来追加到结果列表后面;重复此过程直至满足条件或者变为空之后才可让新的操作数进入其中等待后续计算[^2]。 具体实现可以参考下面这段完整的函数代码片段: ```c #include <stdio.h> #include <stdlib.h> // ... 上述定义部分 ... int precedence(char op) { switch(op){ case '+': case '-': return 1; case '*': case '/': return 2; default : return 0; } } void InfixToPostfix(const char infix[], char postfix[]) { int i = 0, j = 0; LinkStack s; InitStack(&s); while(infix[i]!='\0'){ if(isdigit(infix[i]) || isalpha(infix[i])){ postfix[j++] = infix[i++]; }else{ switch(infix[i]){ case '(': Push(&s,infix[i++]); break; case ')': while(!IsEmpty(&s)&&GetTop(&s)!='(') postfix[j++]=Pop(&s); Pop(&s); // Remove the '(' from stack. ++i; break; case '+': case '-': case '*': case '/': while(!IsEmpty(&s)&&(precedence(GetTop(&s)) >= precedence(infix[i]))) postfix[j++]=Pop(&s); Push(&s,infix[i++]); break; default : ++i; } } } while(!IsEmpty(&s)){ postfix[j++]=Pop(&s); } postfix[j]='\0'; } ``` 上述方法能够有效地利用链表作为辅助工具,在保持原有数据不变的情况下完成了由中缀表示法到后缀表示法之间的变换工作。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值