1. 程式人生 > >資料結構__不含括號的加減乘除法混合運算

資料結構__不含括號的加減乘除法混合運算

這個程式我一共寫了5個檔案,4個是標頭檔案,最後1個則是main函式的cpp檔案。

第一個檔名為head.h

用於包含一些基本的標頭檔案,如下所示:

#pragma once
#include<iostream>
#include<stdlib.h>
#include<string>
using namespace std;

第二個檔名為stack.h

用於定義基本的棧和相應的棧操作,如下所示:

#pragma once
#include"head.h"

struct node
{
	double data;
	node *next;
public:
	node();
};

node::node() {}

class stack
{
private:
	node* top;
public:
	stack() { top = NULL; }
	~stack();
	void push(double e);
	double pop();
	double getTop();
	bool isEmpty() { if (top == NULL) return true; else return false; }
};

double stack::getTop()
{
	if (top != NULL) 
		return top->data;
}

stack::~stack()
{
	node* p;
	while (top)
	{
		p = top->next;
		delete top;
		top = p;
	}
}

void stack::push(double e)
{
	node* p = new node;
	if (!p)
	{
		cout << "記憶體分配失敗" << endl;
		return;
	}
	p->data = e;
	p->next = top;
	top = p;
}

double stack::pop()
{
	if (top == NULL)
	{
		cout << "溢位" << endl;
	}
	double temp = top->data;
	node* p = top;
	top = top->next;
	delete p;
	return temp;
}

第三個檔名是queue.h

用於定義基本的佇列和相關的操作,如下:

#pragma once
#include"head.h"

struct Node
{
	double data;
	Node *next;
};
class sqqueue 
{
private:
	Node *front;
	Node *rear;
public:
	sqqueue();
	~sqqueue();
	void enqueue(double e);
	double dequeue();
	bool isEmpty();
	double getFront();
};

double sqqueue::getFront()
{
	return front->next->data;
}

sqqueue::sqqueue()
{
	front = new Node;
	front->next = NULL;
	rear = front;
}

sqqueue::~sqqueue()
{
	Node *p=NULL;
	while (front != NULL)
	{
		p = front;
		front = front->next;
		delete p;
	}
}

void sqqueue::enqueue(double e)
{
	Node *s = new Node;
	s->data = e;
	s->next = rear->next;
	rear->next = s;
	rear = s;
	if (front->next == NULL)
		front->next = s;
}

double sqqueue::dequeue()
{
	double e;
	Node *p = NULL;
	if (rear == front)
	{
		cout << "下溢" << endl;
	}
	p = front->next;
	e = p->data;
	front->next = p->next;
	if (p->next == NULL)
		rear = front;
	delete p;
	return e;
}

bool sqqueue::isEmpty()
{
	if (rear == front) return true;
	else return false;
}

第四個檔名是change.h

裡面有兩個函式,第一個名為change的函式作用是“逆波蘭”,第二個Cal函式則是計算字尾表示式並輸出最後的計算結果,如下:

#pragma once
#include"queue.h"
#include"stack.h"

sqqueue output;
stack s;
stack a;

void change(string str)
{
	double num;
	double temp;
	for (int i = 0; i < str.length();)
	{
		if (str[i] >= '0'&&str[i] <= '9')
		{
			temp = str[i++] - '0';
			while (i < str.length() && str[i] >= '0'&&str[i] <= '9')
			{
				temp = temp * 10 + (str[i] - '0');
				i++;
			}
			output.enqueue(temp);
		}
		else
		{
			if (((str[i] == '+' || str[i] == '-')&&(s.getTop() == -3|| s.getTop() == -4))|| ((str[i] == '+' || str[i] == '-') && (s.getTop() == -1 || s.getTop() == -2))|| ((str[i] == '*' || str[i] == '/') && (s.getTop() == -3 || s.getTop() == -4)))
			{
				while (!s.isEmpty())
				{
					output.enqueue(s.pop());
				}
			}
			switch (str[i])
			{
			case '+':s.push(-1); break;
			case '-':s.push(-2); break;
			case '*':s.push(-3); break;
			case '/':s.push(-4); break;
			default:break;
			}
			i++; 
		}
	}
	while (!s.isEmpty())
	{
		output.enqueue(s.pop());
	} 
}

void Cal()
{
	double temp;
	double r, l;
	while (!output.isEmpty())
	{
		if (output.getFront() >= 0)
		{
			a.push(output.dequeue());
		}
		else
		{
			double x = output.dequeue();
			if (x == -1)
			{
				r = a.pop();
				l = a.pop();
				temp = l + r;
				a.push(temp);
			}
			else if (x == -2)
			{
				r = a.pop();
				l = a.pop();
				temp = l - r;
				a.push(temp);
			}
			else if (x == -3)
			{
				r = a.pop();
				l = a.pop();
				temp = l * r;
				a.push(temp);
			}
			else if (x == -4)
			{
				r = a.pop();
				l = a.pop();
				temp = l / r;
				a.push(temp);
			}
		}
	}
	cout << a.pop() << endl;
}

最後一個cpp檔案是用來寫main函式的,很簡潔,沒啥好說的。檔名就叫main.cpp:

#include"change.h"
int main(void)
{
	string str;
	cin >> str;
	change(str);
	Cal();
	system("pause");
	return 0;
}

個人以為,主要是第四個叫change的檔案需要注意,尤其是逆波蘭的步驟。。。。一不小心寫錯一點點就會有記憶體訪問錯誤,原因是退棧出棧入隊出隊的操作容易不小心寫混,導致讀取資料的data指標指向NULL。主要是找BUG會找很久很久。

下面展示幾個測試資料: