データ構造学習ノートのスタック(デジタル変換、括弧マッチング、表式求値逆ポーランド)

8225 ワード

#include 
#include 
#include 
#include 
#include 
#include //gcc6.3   
#include 
#include 
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
	/* +*/'>', '>', '', '>',
	/* -*/'>', '>', '', '>',
	/* **/'>', '>', '>', '>', '', '>',
	/* /*/'>', '>', '>', '>', '', '>',
	/* ^*/'>', '>', '>', '>', '>', '', '>',
	/* !*/'>', '>', '>', '>', '>', '>', ' ', '>', '>',
	/* (*/'
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
Stack::Stack(int c)
{
	_elem = new T[_capacity = c];
	_buttom = 0;
	_top = 0;
}

template
Stack::~Stack()
{
	delete[] _elem;
}

template
Rank Stack::GetSize()
{
	return _top - _buttom;
}

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

template
void Stack::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
void Stack::push(T const &e)
{
	if (GetSize() >= _capacity) expand();
	_elem[_top++] = e;
}

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

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

template
void Stack::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 &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 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
bool permutation(Stack &s, const T exp[], int expSize)
{//s.pop() -> exp[] s    ,     push 
	if (expSize != s.GetSize()) return false;
	Stack 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& 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 opnd;//    
	Stack 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 '': {
			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 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 c;
	convert(c, 2013, 2);
	while (!c.isEmpty())cout << c.pop();
	cout << endl;
	char a[] = "adwasfweef";
	cout << paren(a);
	char b[] = "(!c.isEmpty())cout< si;
	for (int i = 5; i > 0; i--) si.push(i);
	int arri[] = { 4, 5, 3, 2, 1 };
	cout << permutation(si, arri, 5);
	Stack 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;
}