字符串表達式的計算(c++版)

一.字符串表達式的解析

      z字符串表達式在棧結構的應用中是一個非常典型的列子,其算法設計思維充分的利用了棧的特性.

     類如: "1+8*9+(4+5)*7" 完成字符串表達式的計算主要分爲2個步驟;

    1. 將中綴轉化爲後綴

              按照(*/+-)的優先級;分別創建2個棧用來貯存數字和符號,從第一個元素遍歷,遇到數字進入數字棧,遇到符號進入符號棧,如果符號入棧是棧頂符號優先級大於或小於此符號優先級,則將棧頂元素壓入數字棧,直到元素遍歷完將符號棧的元素全部壓入棧中;

       2.將後綴表達式計算

     遍歷全部元素,遇到數字數字壓入新棧中,遇到符號將此符號作爲前面2個數字的運算符,計算結果壓入新棧,直到計算完成

原理圖:

                          

二.源代碼的實現

        

#include <iostream>
#include <cstdio>
#include <cstring> 
#include <cstdlib>
const int  SIZE = 100; // 棧的初始容量
const int  ADDSIZE = 5; // 棧的單位增加容量
using namespace std;// 命名空間
const int INF = -0xfffffff;// 用於空棧時防止尷尬,返回一個不能讀取的地址,讓讀取的人尷尬;
template <class T>
struct Strack
{
	T *top;// 棧頂的指針
	T *base;// 棧底的指針
	int strackSize;//棧容量
	void init()//棧的初始化
	{
		base = (T *)malloc(SIZE * sizeof(T));//分配內存
		top = base;
		strackSize = SIZE;
	}

	T Top()
	{// 返回棧頂元素
		if (top == base)
			return INF;// 返回尷尬地址
		return *(top - 1);
	}

	bool pop()
	{// 刪除棧頂元素
		if (top == base)
			return false;
		top--;
		return true;
	}

	void push(T x)
	{//棧頂插入元素
		if (isPull()) {//如果內存不夠重新分配內存
			base = (T *)realloc(base, (strackSize + ADDSIZE)*(sizeof(T)));
			top = base + strackSize;
			strackSize += ADDSIZE;
		}
		*top++ = x;
	}

	bool isEmpty()
	{//判斷棧是否爲空
		if (top == base)
			return true;
		return false;
	}

	bool isPull()//判滿函數
	{
		if (top - base == strackSize)// 一次push一個所以當top - base = strackSize時滿
			return true;
		else
			return false;
	}
};

int compareNumber(char x)//用來比較符號的優先級
{
	if (x == '+' || x == '-')
		return 0;
	if (x == '*' || x == '/')
		return 1;
	return -1;
}

void change(char *mid, char *suxfix)//中綴表達式轉換爲後綴表達式     
{
	int i = 0, len = strlen(mid), mid_index = 0;
	char c;
	Strack<char >intElements;// int數據集
	intElements.init();
	intElements.push('#');// 特殊符號用來區分元素
	while (i < len)
	{
		if (mid[i] == '(')
		{
			intElements.push(mid[i]);
			i++;
		}
		else if (mid[i] == ')')
		{
			while (intElements.Top() != '(')
			{
				suxfix[mid_index++] = intElements.Top();
				suxfix[mid_index++] = ' ';
				intElements.pop();
			}
			intElements.pop();
			i++;
		}
		else if (mid[i] == '+' || mid[i] == '-' || mid[i] == '/' || mid[i] == '*')
		{
			while (compareNumber(intElements.Top()) >= compareNumber(mid[i]))
			{
				suxfix[mid_index++] = intElements.Top();
				suxfix[mid_index++] = ' ';
				intElements.pop();
			}
			intElements.push(mid[i]);
			i++;
		}
		else if (mid[i] >= '0'&&mid[i] <= '9')
		{
			while (mid[i] >= '0'&&mid[i] <= '9')
			{
				suxfix[mid_index++] = mid[i];
				i++;
			}
			suxfix[mid_index++] = ' ';
		}
		else
		{

		}
	}
	while (intElements.Top() != '#') {
		suxfix[mid_index++] = intElements.Top();
		suxfix[mid_index++] = ' ';
		intElements.pop();
	}
	suxfix[mid_index] = 0;
}

double countSuxfix(char *suxfix)//計算後綴表達式   suxfix後綴表達式
{
	int len = strlen(suxfix);
	double x;
	Strack <int >intElements;
	intElements.init();
	int i = 0;
	while (i<len) {
		if (suxfix[i] == ' ')// 用於表達式有效字符集用完跳出循環
		{
			i++;
			continue;
		}
		switch (suxfix[i])
		{
		case '+':
			x = intElements.Top();//根據原理圖看
			intElements.pop();
			x = intElements.Top() + x;
			intElements.pop(); i++;
			break;
		case '-':
			x = intElements.Top();
			intElements.pop();
			x = intElements.Top() - x;
			intElements.pop();
			i++;
			break;
		case '*':
			x = intElements.Top();
			intElements.pop();
			x = intElements.Top()*x;
			intElements.pop();
			i++;
			break;
		case '/':
			x = intElements.Top();
			intElements.pop();
			x = intElements.Top() / x;
			intElements.pop();
			i++;
			break;
		default:
		{
			x = 0;
			while (suxfix[i] >= '0'&&suxfix[i] <= '9') {
				x = x * 10 + suxfix[i] - '0';// 連續2個數,第一個*10,以此類推
				i++;
			}
		}
		}

		intElements.push(x);
	}
	return intElements.Top();
}
int main()
{
	char str[1000];
	char newStr[1000];
	scanf("%s", str);
	change(str, newStr);
	cout << newStr << endl;
	cout << countSuxfix(newStr) << endl;
	return 0;
}

--------------------------------------------------------------------------over-----------------------------------------------------------------------------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章