• 表达式的后缀表示


    表达式的后缀表示

    基本要求

    • 设计一转换程序,将输入的任一表达式转换成相应的后缀形式后输出。
    • 为简单起见,假定运算对象只含变量,且每个变量名以单字母表示;运算符仅含+、-、*、/和圆括号;表达式以分号“;”结尾。在转换过程中,要求作必要的语法检查,例如圆括号是否配对,单词是否合法等。
    • 分别编写转换程序的非递归与递归算法

    用栈实现非递归算法。首先给出栈的类定义,建议用一个头文件保存

    #include<iostream>
    #include<assert.h>
    using namespace std;
    const int stackIncreament = 20;//溢出时的扩容
    template<class T> 
    class SeqStack
    {
    public:
    	T * elements;
    	int top;
    	int maxSize;
    	void overflowProcess();
    public:
    	SeqStack(int sz =50);
    	~SeqStack(){ delete[]elements; }
    	void Push( const T& x);
    	bool Pop(T& x);
    	bool Top(T& x);
    	bool IsEmpty()const { return(top == -1) ? true : false; }
    	bool IsFull()const { return (top == maxSize - 1) ? true : false; }
    	int getSize()const { return top + 1; };
    	void MakeEmpty() { top = -1; }
    	friend ostream&operator<<(ostream& os, SeqStack<T>&s);
    };
    template <class T>
    SeqStack<T>::SeqStack(int sz) :top(-1), maxSize(sz)
    {
    	//建立最大尺度为sz的空栈
    	elements = new T[maxSize];//创建数组
    	assert(elements != NULL);//断言:动态分配内存成功与否
    }
    template<class T>
    void SeqStack<T>::overflowProcess()
    {
    	T* newArray = new T[maxSize + stackIncreament];
    	if (newArray == NULL) { cerr << " new error!" << endl; exit(1); }
    	for (int i = 0; i <= top; i++)newArray[i] = elements[i];
    	maxSize = maxSize + stackIncreament;
    	delete[]elements;
    	elements = newArray;
    }
    template<class T>
    void SeqStack<T>::Push(const T&x)
    {
    	if(IsFull()==true) overflowProcess();
    	elements[++top] = x;
    }
    template<class T>
    bool SeqStack<T>::Pop(T &x)
    {
    	if (IsEmpty() == true)return false;
    	x = elements[top--];
    	return true;
    }
    template <class T>
    bool SeqStack<T>::Top(T&x)
    {
    	if (IsEmpty())return false;
    	x = elements[top];
    	return true;
    }
    

    语法检查函数,优先级预处理,都可以视为pre-operation

    bool check_op(char a)
    {
    	if (a == '*' || a == '/' || a == '+' || a == '-' || a == '%')return true;
    	return false;
    }
    map<char, int>isp; map<char, int>icp;
    void Init()
    {
    
    	isp['#'] = 0; isp['('] = 1; isp['*'] = 5; isp['/'] = 5; isp['%'] = 5; isp['+'] = 3; isp[')'] = 6; isp['-'] = 3;
    	icp['#'] = 0; icp['('] = 6; icp['*'] = 4; icp['/'] = 4; icp['%'] = 4; icp['+'] = 2; icp[')'] = 1; icp['-'] = 2;
    }
    bool pre_check(string expression)//语法检查
    {
    	int numl = 0, numr = 0;
    	//最前面为操作符或者最后面为操作符,因为要求表达式以';'结尾,检查倒数第二个
    	if (check_op(expression[0]) || check_op(expression[expression.size() - 2]))
    	{
    		cout << "表达式格式错误,please check!" << endl;
    		return false;
    	}
    
    	for (int i = 0; i < expression.size()-1; i++)
    	{ 
    		//连续的操作数
    		if (isalpha(expression[i]) && isalpha(expression[i + 1])) {
    			cout << "表达式格式错误,please check!" << endl;
    			return false;
    		}
    		//连续的操作符
    		if (check_op(expression[i]) && check_op(expression[i + 1])) {
    			cout << "表达式格式错误,please check!" << endl;
    			return false;
    		}
    		//左右括号是否匹配
    		if (expression[i] == '(')numl++;
    		if (expression[i] == ')')numr++;
    		//首先出现左括号
    		if (numl < numr)
    		{
    			cout << "表达式格式错误,please check!" << endl;
    			return false;
    		}
    	
    	}
    	if (numl != numr) {
    		cout << "表达式格式错误,please check!" << endl;
    		return false;
    	}
    		return true;
    	
    }
    

    非递归算法,数据结构stack实现

    void inffix_suffix(string expression)
    {
    	if (!pre_check(expression))return;
    	//string sss = ";";
    	Init();
    	int i = 0;
    	
    	SeqStack<char>s;
    	char ch = '#', ch1, op;
    	s.Push(ch); ch = expression[i++];
    	while (!s.IsEmpty() && ch != '#')
    	{
    		if (isalpha(ch)) { cout << ch; ch = expression[i++]; }//操作数直接输出
    		else
    		{
    			s.Top(ch1);//栈顶元素ch1
    			if (isp[ch1] < icp[ch]) { s.Push(ch); ch = expression[i++]; }//新输入的操作符优先级高,进栈
    			else if (isp[ch1] > icp[ch]) { s.Pop(op); cout << op; }//优先级低,退栈
    			else {
    				s.Pop(op);//优先级相同,先左后右
    				if (op == '(')ch = expression[i++];//此时说明,栈内的是'(',栈外的是')',ch = expression[i++]表示直接到')'的后一个
    			}
    		}
    	}
    	cout << endl;
    }
    
    

    递归写法

    //此处没有再次进行语法检查,没有调用pre_check(expression))和Init();因为在main函数中,非递归先调用,以及调用前面两个函数
    void inffix_suffix(string expression)
    {
    	if (!pre_check(expression))return;
    	//string sss = ";";
    	Init();
    	int i = 0;
    	
    	SeqStack<char>s;
    	char ch = '#', ch1, op;
    	s.Push(ch); ch = expression[i++];
    	while (!s.IsEmpty() && ch != '#')
    	{
    		if (isalpha(ch)) { cout << ch; ch = expression[i++]; }//操作数直接输出
    		else
    		{
    			s.Top(ch1);//栈顶元素ch1
    			if (isp[ch1] < icp[ch]) { s.Push(ch); ch = expression[i++]; }//新输入的操作符优先级高,进栈
    			else if (isp[ch1] > icp[ch]) { s.Pop(op); cout << op; }//优先级低,退栈
    			else {
    				s.Pop(op);//优先级相同,先左后右
    				if (op == '(')ch = expression[i++];//此时说明,栈内的是'(',栈外的是')',ch = expression[i++]表示直接到')'的后一个
    			}
    		}
    	}
    	cout << endl;
    }
    
    

    结束啦,欢迎大家指出错误之处

    不疯魔不成活
  • 相关阅读:
    LamBda学习(一)
    如何返回一个只读泛型集合
    Socket编程笔记同步
    如何快速读取大文件(看csdn一网友要求写的)没有测试具体的速度。
    如何实现项目脚本的批量生成
    如何实现WORD查找完成后不提示的代码
    W32/Pate.a 病毒处理小记
    在WORD中用VBA实现光标移动与内容选择
    2. WCF 消息操作
    3. WCF 异常处理
  • 原文地址:https://www.cnblogs.com/gzr2018/p/9972914.html
Copyright © 2020-2023  润新知