数据结构学习笔记之栈(含数制转换,括号匹配,表达式求值转逆波兰)

#include <iostream>
#include <cstring>
#include <ctype.h>
#include <string>
#include <cstring>
#include <malloc.h>//gcc6.3可不加
#include <stdlib.h>
#include <algorithm>
using namespace std;
typedef int Rank;
#define DEFAULT_CAPACITY 3
#define N_OPTR 9
const char OPSET[N_OPTR] = { '+', '-', '*', '/', '^', '!', '(', ')', '\0' };
const char pri[N_OPTR][N_OPTR] = {
	//横当前运算符,竖栈顶运算符
	//     +    -    *    /    ^    !    (    )    \0
	/* +*/'>', '>', '<', '<', '<', '<', '<', '>', '>',
	/* -*/'>', '>', '<', '<', '<', '<', '<', '>', '>',
	/* **/'>', '>', '>', '>', '<', '<', '<', '>', '>',
	/* /*/'>', '>', '>', '>', '<', '<', '<', '>', '>',
	/* ^*/'>', '>', '>', '>', '>', '<', '<', '>', '>',
	/* !*/'>', '>', '>', '>', '>', '>', ' ', '>', '>',
	/* (*/'<', '<', '<', '<', '<', '<', '<', '=', ' ',
	/* )*/' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
	/*/0*/'<', '<', '<', '<', '<', '<', '<', ' ', '=',
};

template <typename T>
class Stack {
private:
	Rank _top;
	Rank _buttom;
	int _capacity;
	T *_elem;
protected:
	void expand();
	void shrink();
public:
	Stack(int c = DEFAULT_CAPACITY);
	~Stack();
	Rank GetSize();
	bool isEmpty();
	void push(T const &e);
	T pop();
	T &top();
	void show();
};

template<typename T>
Stack<T>::Stack(int c)
{
	_elem = new T[_capacity = c];
	_buttom = 0;
	_top = 0;
}

template<typename T>
Stack<T>::~Stack()
{
	delete[] _elem;
}

template<typename T>
Rank Stack<T>::GetSize()
{
	return _top - _buttom;
}

template<typename T>
bool Stack<T>::isEmpty()
{
	return (_top == _buttom) ? true : false;
}

template<typename T>
void Stack<T>::expand()
{
	_capacity = max(_capacity, DEFAULT_CAPACITY);
	T *oldelem = _elem;
	_elem = new T[_capacity <<= 1];
	for (int i = 0; i < GetSize(); ++i)
		_elem[i] = oldelem[i];
	delete[] oldelem;
}

template<typename T>
void Stack<T>::push(T const &e)
{
	if (GetSize() >= _capacity) expand();
	_elem[_top++] = e;
}

template<typename T>
T &Stack<T>::top()
{
	return _elem[_top - 1];
}

template<typename T>
void Stack<T>::shrink()
{
	//cout<<"start shrink"<<endl;
	_capacity = max((_top - _buttom) * 2, DEFAULT_CAPACITY);
	T *oldelem = _elem;
	_elem = new T[_capacity];
	for (int i = 0; i <= (_top - _buttom); ++i)
		_elem[i] = oldelem[i];
	delete[] oldelem;
}

template<typename T>
T Stack<T>::pop()
{
	_top--;
	if (GetSize() * 2 < _capacity) shrink();
	return _elem[_top];
}

template<typename T>
void Stack<T>::show()
{
	cout << "top: " << _top << "\tbuttom: " << _buttom << endl;
	cout << "size: " << GetSize() << "\tcapacity: " << _capacity << endl;
	for (int i = 0; i < GetSize(); ++i)
		cout << _elem[i] << "\t";
	cout << endl;
}

//进制转换n进制转b进制(逆序输出)
void convert(Stack<char> &s, int n, int b)
{
	static char digit[] = { '0', '1', '2', '3', '4', '5',
	'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
	while (n > 0)
	{
		s.push(digit[n%b]);
		n /= b;
	}
}

//括号匹配
bool paren(const char exp[])
{
	Stack<char> s;
	for (int i = 0; i < strlen(exp); ++i)
	{//左括号入栈,遇到右括号pop。栈空还能遇到右括号则不匹配
		if ('(' == exp[i])s.push(exp[i]);
		else if (!s.isEmpty() && ')' == exp[i])s.pop();
		else if (s.isEmpty() && ')' == exp[i])return false;
	}
	return s.isEmpty();//栈空匹配,不空失配
}

//栈混洗的种数为(2n)!/((n+1)!n!)
//对于任意三个元素123出312必非栈混洗(充要条件)
template<typename T>
bool permutation(Stack<T> &s, const T exp[], int expSize)
{//s.pop() -> exp[] s是倒序的,先出栈的后push入
	if (expSize != s.GetSize()) return false;
	Stack<T> t;
	for (int i = 0, j = 0; i < expSize; ++i)
	{
		t.push(s.pop());
		while (t.GetSize() > 0 && t.top() == exp[j])
		{
			t.pop();
			j++;
		}
	}
	return (t.isEmpty() == true) ? true : false;
}

//读入数据,处理多位数,(从属于evaluate)
void readNumber(char *&p, Stack<float>& stk)
{
	stk.push(float(*p - '0'));
	while (isdigit(*(++p))) stk.push(stk.pop() * 10 + (*p - '0'));
	if ('.' != *p)return;
	float fraction = 1;
	while (isdigit(*(++p)))stk.push(stk.pop() + (*p - '0')*(fraction /= 10));
}

//判断优先级(从属于evaluate)
char orderBetween(char &e, char &s)
{
	int i, j;
	for (i = 0; i < N_OPTR; ++i)
		if (e == OPSET[i])break;
	for (j = 0; j < N_OPTR; ++j)
		if (s == OPSET[j])break;
	return pri[i][j];
}

//一二元运算计算(从属于evaluate)
float calcu(float p1, char op, float p2 = 0)
{
	switch (op) {
	case '+':return p1 + p2;
	case '-':return p1 - p2;
	case '*':return p1 * p2;
	case '/':return p1 / p2;
	case '^': {
		float c = 1;
		while (p2--) c = c * p1;
		return c;
	}
	case '!': {
		if (p1 == 0)return 1;
		else return p1 * calcu(p1 - 1, '!');//递归求阶乘
	}
	}
}

//将数字写入逆波兰
void append(char *&rpn, float opnd)
{
	int n = strlen(rpn);
	char buf[64];
	if (opnd != float(int(opnd)))sprintf(buf, "%.2f \0", opnd); //小数
	else sprintf(buf, "%d \0", int(opnd)); //整数
	rpn = (char*)realloc(rpn, sizeof(char)*(n + strlen(buf) + 1)); //扩展空间,需要stdlib.h malloc.h
	strcat(rpn, buf); //RPN加长
}

//将运算符写入逆波兰
void append(char *& rpn, char optr) { //将运算符接至RPN末尾
	int n = strlen(rpn); //RPN当前长度(以'\0'结尾,长度n + 1)
	rpn = (char*)realloc(rpn, sizeof(char) * (n + 3)); //扩展空间
	sprintf(rpn + n, "%c ", optr); rpn[n + 2] = '\0'; //接入指定的运算符
}

//中缀表达式求值的主体部分
float evaluate(char *S, char *& rpn)//*&意为数组引用
{
	Stack<float> opnd;//运算数栈
	Stack<char> optr;//运算值栈
	optr.push('\0');//头哨兵,和字符串结尾的'\0'匹配
	int i = 0;
	while (!optr.isEmpty())
	{
		if (isdigit(*S))//当前字符为操作数,isdigit判断是否为10进制数
		{
			readNumber(S, opnd);//读入数字
			append(rpn, opnd.top());
		}
		else switch (orderBetween(optr.top(), *S))//当前字符为运算符
		{
		case '<': {
			optr.push(*S);
			S++;
			break;
		}
		case '=': {
			optr.pop();
			S++;
			break;
		}
		case '>': {
			char op = optr.pop();
			append(rpn, op);
			if (op == '!') {
				float temp = calcu(opnd.top(), op);//一元运算的情况
				opnd.pop();
				opnd.push(temp);
			}
			else {
				float pOpnd2 = opnd.top();
				opnd.pop();
				float pOpnd1 = opnd.top();
				opnd.pop();
				opnd.push(calcu(pOpnd1, op, pOpnd2));//二元运算的情况
			}
			break;
		}
		}
	}
	return opnd.top();
}

int main()
{
	Stack<int> s;
	s.push(1);
	s.push(2);
	s.push(3);
	s.push(4);
	s.show();
	cout << s.isEmpty() << endl;
	cout << s.top() << endl;
	cout << s.pop() << endl;
	s.show();
	cout << s.top() << endl;
	cout << s.pop() << endl;
	s.show();
	cout << s.top() << endl;
	cout << s.pop() << endl;
	s.show();
	cout << s.top() << endl;
	cout << s.pop() << endl;
	cout << s.isEmpty() << endl;
	s.show();
	cout << endl;
	Stack<char> c;
	convert(c, 2013, 2);
	while (!c.isEmpty())cout << c.pop();
	cout << endl;
	char a[] = "adwasfweef";
	cout << paren(a);
	char b[] = "(!c.isEmpty())cout<<c.pop();";
	cout << paren(b);
	char d[] = "((!c.isEmpty()cout<<c.pop()())";
	cout << paren(d);
	Stack<int> si;
	for (int i = 5; i > 0; i--) si.push(i);
	int arri[] = { 4, 5, 3, 2, 1 };
	cout << permutation(si, arri, 5);
	Stack<int> s2;
	for (int i = 5; i > 0; i--) s2.push(i);
	int arr2[] = { 1, 5, 3, 2, 4 };
	cout << permutation(s2, arr2, 5) << endl;
	char *r = (char*)malloc(sizeof(char) * 1);
	r[0] = '\0';
	char exp1[] = "2+2";
	char exp2[] = "20*(4.5-3)";
	char exp3[] = "5!-6.7";
	char exp4[] = "(1+2^3!-4)*(5!-(6-(7-(89-0!))))";
	cout << evaluate(exp1, r) << endl;
	cout << r << endl;
	r[0] = '\0';
	cout << evaluate(exp2, r) << endl;
	cout << r << endl;
	r[0] = '\0';
	cout << evaluate(exp3, r) << endl;
	cout << r << endl;
	r[0] = '\0';
	cout << evaluate(exp4, r) << endl;
	cout << r << endl;
	return 0;
}

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值