数据结构 实验二 栈和队列的应用

在这里插入图片描述

详细过程

顺序栈的实现

#include <iostream>
#include <cstdlib>
using namespace std;

const int STACK_INIT_SIZE = 20;
const int ERROR = 0;
const int OK = 1;
const int EMPTY = 0;

typedef int Status;

template <class T>
class SqStack
{
public:
	SqStack();
	~SqStack();
	Status Push(T e);
	Status Pop(T &e);
	Status GetTop(T &e) const;
	int StackLength() const;
	Status IsEmpty();
	void DispStack();

private:
	T * base;
	T *top;		//栈顶指针
	int stacksize;
};

//初始化一个栈
template <class T>
SqStack<T>::SqStack()
{
	base = new T[STACK_INIT_SIZE];
	top = base;
	stacksize = STACK_INIT_SIZE;
}

//释放一个栈
template <class T>
SqStack<T>::~SqStack()
{
	delete[] base;
}

//取顺序栈栈顶元素算法
template <class T>
Status SqStack<T>::GetTop(T &e) const
{
	if (top == base)
	{
		return ERROR;
	}
	e = *(top - 1);
	return OK;
}

//顺序栈入栈
template <class T>
Status SqStack<T>::Push(T e)
{
	if (top - base >= stacksize)
	{
		return ERROR;
	}
	*top++ = e;	//先赋值,再加指针
	return OK;
}

//顺序栈出栈
template <class T>
Status SqStack<T>::Pop(T &e)
{
	if (top == base)
	{
		return ERROR;
	}
	e = *--top;		//先减指针,再取值
	return OK;
}

//求栈长
template <class T>
int SqStack<T>::StackLength() const
{
	int sizeCount = 0;
	T *p = top - 1;
	while (p >= base)
	{
		sizeCount++;
		p--;
	}
	return sizeCount;
}

template <class T>
Status SqStack<T>::IsEmpty()	//空栈为0,非空栈为1;
{
	if (top == base)
	{
		return EMPTY;
	}
	else
	{
		return OK;
	}
}

template <class T>
void SqStack<T>::DispStack()
{
	T *p = top - 1;
	while (p >= base)
	{
		cout << *p << " ";
		p--;
	}
	cout << endl;
}

bool In(char c)
{
	if (c>48 && c<57)
	{
		return false;
	}
	else
	{
		return true;
	}
}


//判断优先级
char Precede(char o1, char o2)
{
	char f = ' ';

	switch (o2)
	{
	case '+':
	case '-':
		if (o1 == '(' || o1 == '#')	//栈中符号优先级低
		{
			f = '<';
		}
		else
		{
			f = '>';
		}
		break;
	case '*':
	case '/':
		if (o1 == '*' || o1 == '/' || o1 == ')')
		{
			f = '>';
		}
		else
		{
			f = '<';
		}
		break;
	case '(':
		if (o1 == ')')
		{
			cout << "括号匹配错误!" << endl;
			exit(ERROR);
		}
		else
		{
			f = '<';
		}
		break;
	case ')':
		switch (o1)
		{
		case '(':
			f = '=';	//括号匹配
			break;
		case '#':
			cout << "输入了错误的括号!~" << endl;
			exit(ERROR);
		default:
			f = '>';	//其他情况站定元素的优先级更大
		}
		break;
	case '#':
		switch (o1)
		{
		case '#':
			f = '=';
			break;
		case '(':
			cout << "表达式中有多余的括号!!" << endl;
			exit(ERROR);
		default:
			f = '>';
		}

	}
	return f;
}

//运算函数
int Operate(int a, char theta, int b)
{
	switch (theta)
	{
	case '+':
		return a + b;
		break;
	case '-':
		return a - b;
		break;
	case '*':
		return a * b;
		break;
	case '/':
		return a / b;
		break;
	}
	return 0;
}

int EvalExpr(char *ptr)
{
	SqStack<char> OPTR;	//操作符栈
	OPTR.Push('#');		//表达式起始符为'#'
	SqStack<int> OPND;	//操作数栈
	char op, c, theta = ' ', x, m;
	int a = 0;	//操作数a
	int b = 0;	//操作数b

	c = *ptr++;		//每一个数当做字符取出,ptr遍历后移
	OPTR.GetTop(op);
	while (c != '#' || op != '#')
	{
		if (!In(c))	//如果是数字直接进栈
		{
			m = atoi(&c);	//将字符转化为数字
			OPND.Push(m);	//数字入栈
			c = *ptr++;		//指针后移
		}
		else	//如果是符号的话,则先将这个符号与栈顶符号进行比较
		{
			switch (Precede(op, c))
			{
			case '<':			//栈中符号优先级低,继续进栈
				OPTR.Push(c);
				c = *ptr++;
				break;
			case '=':			//优先级相等时,说明遇到括号,需要托括号
				OPTR.Pop(x);		//脱括号
				c = *ptr++;
				break;
			case '>':			//栈中符号优先级高时,先计算,再将结果压入栈中
				OPTR.Pop(theta);	//运算符
				OPND.Pop(b);		//操作数
				OPND.Pop(a);
				OPND.Push(Operate(a, theta, b));	//将新的运算结果插到栈中
				break;
			}
		}
		OPTR.GetTop(op);	//每一次更新当前栈顶符号
	}

	OPND.GetTop(a);		//计算结果
	return a;
}

//将中缀式转化为后缀式
char *change(char *ptr)
{
	char *result = new char;
	int i = 0;
	SqStack<char> OPTR;
	OPTR.Push('#');
	char e = ' ', op = ' ';
	while (*ptr != '#')
	{
		if (!In(*ptr))
		{
			*(result + i++) = *ptr;
		}
		else
		{
			if (*ptr == '(')	//左括号直接进栈
			{
				OPTR.Push(*ptr);
			}
			else if (*ptr == ')')	//右括号出到左括号为止
			{
				do {
					OPTR.Pop(e);
					if (e != '(')
						*(result + i++) = e;	//将不为左括号的元素进栈
				} while (e != '(');
			}
			else
			{
				OPTR.GetTop(op);
				switch (Precede(op, *ptr))
				{
				case '<':
					OPTR.Push(*ptr);
					break;
				case '=':
				case '>':
					do {
						OPTR.Pop(e);
						*(result + i++) = e;
						OPTR.GetTop(op);
					} while (Precede(op, *ptr) == '>');	//有可能出现多个优先的情况(+*  -)
														//+和*号必须都出去
					OPTR.Push(*ptr);
				}
			}
		}// end of else
		ptr++;
	}// end of while

	while (OPTR.IsEmpty() != EMPTY)
	{
		OPTR.Pop(e);
		if (e != '#')
			*(result + i++) = e;
	}
	*(result + i) = '\0';
	return result;
}


//后缀表达式求值
int EvalExpr_RPN(char *exp)
{
	SqStack<int> s;
	int a = 0, b = 0, e = 0;
	while (*exp != '\0')		//没有读取到字符串尾部
	{
		if (!In(*exp))	//读取的字符是数字不是符号
		{
			s.Push(*exp - 48);	//字符转数字‘1’->1;数字直接入栈
		}
		else
		{
			s.Pop(b);
			s.Pop(a);
			s.Push(Operate(a, *exp, b));	//弹出两个数进行运算
		}
		exp++;		//z指针后移
	}
	s.Pop(e);		//计算结果为e
	return e;
}


int main()
{

		char a[17] = "1+2*(5-3)-6/2+4#";
		char *exp = a;
		int opnd = EvalExpr(exp);
		cout<< "作为示例 " << exp << "的计算结果为 " << opnd <<endl;

		cout << exp << "转化为后缀表达式为"  << change(exp) <<endl;
		cout << "后缀表达式求值为" << EvalExpr_RPN(change(exp)) <<endl;

		char b[7] = "4+2*4#";
		char *p = b;
		cout<< p << change(p) <<endl;
		cout<< EvalExpr_RPN(change(p)) << endl;


	return 0;
}

题目要求

参考文献

#include <iostream>
using namespace std;

const int ERROR = 0;
const int OK = 1;
const int EMPTY = 1;

typedef int Status;

template <class T>
struct Node
{
	T data;
	Node<T> *next;
};

template <class T>
class LinkQueue
{
public:
	LinkQueue();
	~LinkQueue();
	Status EnQueue(T e);
	Status DeQueue(T &e);
	int QueueLength();
	Status IsEmpty();
	void DispQueue();
	Node<T>* getFront() const;

private:
	Node<T> *front;
	Node<T> *rear;
};

template <class T>
LinkQueue<T>::LinkQueue()
{
	front = new Node<T>;
	front->next = NULL;
	rear = front;
}

template <class T>
LinkQueue<T>::~LinkQueue()
{
	Node<T> *p = front;
	while(p != rear)
	{
		p = p->next;
		delete front;
		front = p;
	}
	delete rear;
}

template <class T>
Status LinkQueue<T>::EnQueue(T e)
{
	Node<T> *p = new Node<T>;
	if(p == NULL)
	{
		return ERROR;
	}
	p->data = e;
	p->next = NULL;
	rear->next = p;
	rear = p;	//修改尾指针
	return OK;
}

template <class T>
Status LinkQueue<T>::DeQueue(T &e)
{
	Node<T> *p;
	if(front == rear)
	{
		return ERROR;
	}
	p = front->next;
	e = p->data;
	front->next = p->next;
	if(rear == p)	//只有两个元素的情况,此时需要修改rear指针
	{
		rear = front;
	}
	delete p;
	return OK;
}

template <class T>
int LinkQueue<T>::QueueLength()
{
	int count = 0;
	Node<T> *p = front;
	while(p != rear)
	{
		++count;
		p = p->next;
	}
	return count;
}

template <class T>
Status LinkQueue<T>::IsEmpty()
{
	return (front == rear)?EMPTY:!EMPTY;
}

template <class T>
void LinkQueue<T>::DispQueue()
{
	Node<T> *p = front->next;
	while(p != NULL)
	{
		cout << p->data << " ";
		p = p->next;
	}
	cout<<endl;
}

template <class T>
Node<T>* LinkQueue<T>::getFront() const
{
	return front;
}

void SeeDoctor()
{
	int select;		//用户的选择
	int flag = 1;	//flag初始值为1,一旦下班->>退出系统,将其置为0,从而结束
	int find;
	int no;			//病历号

	LinkQueue<int> patientQueue;
	Node<int> *p;	//指向首元节点

	while(flag == 1)	//flag标识着何时退出
	{
		cout << "1:排队 2:就诊 3:查看排队 4:不再排队,余下依次就诊 5:下班 请选择 :";
		cin>>select;

		switch(select)
		{
		case 1:
			cout << "请输入病历号:";
			do
			{
				cin >> no;	//需要判断病历号是否重复
				find = 0;	//find==1表示有重复的元素,需要重新添加
				p = patientQueue.getFront()->next;
				while(p != NULL && !find)	//遍历查找
				{
					if(p->data == no)
					{
						find = 1;
					}
					else
					{
						p = p->next;
					}
				}

				if(find)
				{
					cout<< "输入的病历号重复,请重新输入:";
				}

			}while(find == 1);//直到输入下一个不在队列中的结束循环

			//直接进队
			patientQueue.EnQueue(no);
			break;

		case 2:
			if(patientQueue.IsEmpty())	//队空
			{
				cout << "没有排队的病人"<<endl;
			}
			else	//队不空的条件
			{
				int temp;
				patientQueue.DeQueue(temp);
				cout << "病人" <<temp << "就诊"<<endl;
			}

			break;

		case 3:
			if(patientQueue.IsEmpty())
			{
				cout << "没有排队的病人。" <<endl;
			}
			else
			{
				cout<< "排队病人" ;
				patientQueue.DispQueue();
			}
			break;

		case 4:
			if(patientQueue.getFront()->next == NULL)
			{
				cout << "没有排队的病人"<<endl;
			}
			else
			{
				cout << "病人按以下的顺序就诊:";
				patientQueue.DispQueue();
			}
			flag = 0;
			break;

		case 5:
			if(patientQueue.getFront()->next != NULL)
			{
				cout << "请排队的人明天就医。" <<endl;
			}
			flag = 0;	//退出的条件
			break;
		//default:

		}
	}

}

int main()
{
	SeeDoctor();
	return 0;
}


运行结果

猜你喜欢

转载自blog.csdn.net/HdUIprince/article/details/83021092