好不容易抽出点时间来复习一下数据结构和算法。
看到堆栈部分。有2道题目,第一道是计算C系列括号匹配校验。第二道是计算算数表达式。
第一道题是思路是
跳过 ' ""字符串,/* // 注释以后。
如果发现{, [, ( 那么入栈,发现 },],) 以后出栈,对比是否匹配。
文件检查完以后,堆栈内为空,说明匹配成功。
(ps一句,很多代码是抄的)
第二道题思路
首先把中缀式转换为后缀式。
转换过程
1)若读入的是操作数,入到输出栈
2)读入的是闭括号,把操作栈中的运算符依次出栈,推入输出栈,一直遇到对应开括号为止,把开括号出栈
3)读入的开括号,进运算符栈
4)读入的是运算符,如果运算符栈优先级高,堆栈运算符出栈,出栈操作一直要进行到栈顶运算符优先级低为止,然后把新的运算符入栈
5)在读入操作符结束扣,把运算符栈中所有剩余运算符依次出栈,放入输出栈
6)计算输出堆表达式的
直接发代码.
先发堆栈的。
#ifndef __ListDemo__List__
#define __ListDemo__List__
#include
template
class ListNode
{
public:
T element;
ListNode *next;
public:
ListNode(T te, ListNode *L):element(te), next(L){}
ListNode(T te):element(te), next(NULL){}
};
template
class Stack {
private:
ListNode *head;
public:
const int isEmpty() const;
void push(T x);
T pop();
T top();
};
template
const int Stack::isEmpty() const
{
return head == NULL;
}
template
void Stack::push(T x)
{
if (head == NULL)
{
head = new ListNode(x);
}
else
{
ListNode *p = new ListNode(x, head);
head = p;
}
}
template
T Stack::pop()
{
if (head == NULL)
{
// return NULL;
}
ListNode *p = head->next;
T x = head->element;
delete head;
head = p;
return x;
}
template
T Stack::top()
{
if (head == NULL)
{
// return NULL;
}
return head->element;
}
#endif /* defined(__ListDemo__List__) */
#ifndef ListDemo_CheckFlag_h
#define ListDemo_CheckFlag_h
#include
#include "List.h"
struct Symbol {
char Token;
int Theline;
};
class CheckFlag
{
private:
enum CommonentType { SlashSlash, SlashStar }; // // or /*
istream & InputStream;
char Ch;
int CurrentLine;
Stack PendingTokens; //没有处理的开括号
int Errors;
private:
int NextChar(); //下1个字符
void PutBackChar(); //把当前字符放回输入流
void SkipComment(CommonentType Start); //跳过 // /*
void SkipQuote(char QuoteType); //跳过 '' 和 ""
char GetNextSymbol(); //获得下1个括号
void CheckMatch(const Symbol & OpSym, const Symbol & ClSym); //查开闭括号是否匹配
public:
CheckFlag(istream & Input) : Errors(0), CurrentLine(1), InputStream(Input){}
~CheckFlag() {}
int CheckBalance(); //检查括号是否匹配
};
int CheckFlag::NextChar()
{
if (!InputStream.get(Ch))
{
return 0;
}
if (Ch == '\n')
{
CurrentLine++;
}
return 1;
}
void CheckFlag::PutBackChar()
{
InputStream.putback(Ch);
if (Ch == '\n')
{
CurrentLine--;
}
}
void CheckFlag::SkipComment(CheckFlag::CommonentType Start)
{
if (Start == SlashSlash) //处理 //
{
while (NextChar() && Ch != '\n')
{}
return;
}
int State = 0; //处理 /*
while (NextChar())
{
if (State && Ch == '/')
{
return;
}
State = Ch == '*';
}
Errors ++;
std::cout << "Comment not is unterminated!" << std::endl;
}
void CheckFlag::SkipQuote(char QuoteType)
{
while (NextChar())
{
if (Ch == QuoteType)
{
return;
}
else if (Ch == '\n') //搜索1行结束,没有找到引号
{
Errors++;
std::cout << "Missing closed quote at line" << CurrentLine << std::endl;
}
else if (Ch == '\\')
{
NextChar(); //跳过\转义
}
}
}
char CheckFlag::GetNextSymbol()
{
while (NextChar())
{
if (Ch == '/')
{
if (NextChar())
{
if (Ch == '*')
{
SkipComment(SlashStar);
}
else if (Ch == '/')
{
SkipComment(SlashSlash);
}
}
}
else if (Ch == '\'' || Ch == '"')
{
SkipQuote(Ch);
}
else if (Ch == '{' || Ch == '(' || Ch == '[' ||
Ch == '}' || Ch == ')' || Ch == ']')
{
return Ch;
}
}
return 0;
}
int CheckFlag::CheckBalance()
{
char LastChar;
Symbol LastSymbol, Match;
Errors = 0, CurrentLine = 1;
while ((LastChar = GetNextSymbol())) //得到当前开闭括号
{
LastSymbol.Token = LastChar;
LastSymbol.Theline = CurrentLine; //当前括号所在行号
switch (LastChar) {
case '(':
case '{':
case '[':
PendingTokens.push(LastSymbol);
break;
case ')':
case '}':
case ']':
if (PendingTokens.isEmpty()) {
Errors++;
std::cout << "Extraneous" << LastChar << "at line" << CurrentLine << endl;
}
else
{
Match = PendingTokens.pop();
CheckMatch(Match, LastSymbol);
}
break;
default:
break;
}
}
//堆栈还有数据
while (! PendingTokens.isEmpty()) {
Errors++;
Match = PendingTokens.pop();
std::cout << "Un matched" << Match.Token << "at line" << Match.Theline << std::endl;
}
return Errors;
}
void CheckFlag::CheckMatch(const Symbol &OpSym, const Symbol &ClSym)
{
if ((OpSym.Token == '(' && ClSym.Token == ')') ||
(OpSym.Token == '{' && ClSym.Token == '}') ||
(OpSym.Token == '[' && ClSym.Token == ']')
)
{
std::cout
<< "Found open flag: " << OpSym.Token << " on line " << OpSym.Theline
<< " close flag: " << ClSym.Token << "on line " << ClSym.Theline
<< std::endl;
}
else
{
std::cout << "does not match" << ClSym.Token << "at line" << OpSym.Theline << std::endl;
Errors++;
}
}
#endif
#ifndef ListDemo_Evaluator_h
#define ListDemo_Evaluator_h
#include "List.h"
#include
class EvalValue
{
public:
int value;
int opType;
public:
EvalValue(int v, int o):value(v),opType(o){}
};
class Evaluator
{
private:
Stack *OpStack; //操作符
Stack *PostFixStack; //数值
enum {
UNKNOW = 100, // 未知
OPAREN, // (
CPAREN, // )
EXP, // ^
MULT, // *
DIV, // /
PLUS, // +
MINUS, // -
};
string *sEval;
private:
int GetCharOp(char Ch);
bool IsDigit(char Ch);
int Digit(char Ch);
void CheckOp(int op);
void openFlagEval(); //括号处理
void orderOpEval(int op); //优先级处理
bool checkOpOrder(int TopOp, int op); //比较优先级
void EvalResult(); //计算结果
string getOpString(int op); //得到运算符的字符串
int CacluateWithValue(int op, int v1, int v2); //计算
public:
Evaluator(const char *strEval);
virtual ~Evaluator() { delete sEval; delete OpStack; delete PostFixStack; }
public:
void Convert();
string Original();
string Converted();
int Caculator();
};
Evaluator::Evaluator(const char *strEval)
{
sEval = new string(strEval);
OpStack = new Stack;
PostFixStack = new Stack;
}
void Evaluator::Convert()
{
int value = 0;
for (int i = 0; i < sEval->size(); i++)
{
char Ch = (*sEval)[i];
if (this->IsDigit(Ch))
{
value = value * 10 + this->Digit(Ch);
}
else
{
if (value != 0)
{
PostFixStack->push(EvalValue(value, 0));
}
if (Ch == ' ')
{
value = 0;
continue;
}
int type = this->GetCharOp(Ch);
if ( type != UNKNOW)
{
this->CheckOp(type);
}
else
{
cout << "error" << endl;
return;
}
value = 0;
}
}
if (value != 0)
{
PostFixStack->push(EvalValue(value, 0));
}
this->EvalResult();
}
string Evaluator::Original()
{
return *sEval;
}
string Evaluator::Converted()
{
Stack *tmp = new Stack();
while (! PostFixStack->isEmpty() )
{
tmp->push(PostFixStack->pop()) ;
}
while (! tmp->isEmpty() )
{
EvalValue eva = tmp->pop();
if (eva.opType != 0)
{
cout << this->getOpString(eva.opType) << " ";
}
else
{
cout << eva.value << " ";
}
}
delete tmp;
cout << endl;
return string("");
}
int Evaluator::Caculator()
{
Stack *reveral = new Stack();
while (! PostFixStack->isEmpty() )
{
reveral->push(PostFixStack->pop()) ;
}
Stack *tmp = new Stack();
while (! reveral->isEmpty() )
{
EvalValue eva = reveral->pop();
if (eva.opType != 0)
{
// cout << this->getOpString(eva.opType) << " ";
int value1 = tmp->pop().value;
int value2 = tmp->pop().value;
int Vtmp = this->CacluateWithValue(eva.opType, value1, value2);
tmp->push(EvalValue(Vtmp, 0));
}
else
{
// cout << eva.value << " ";
tmp->push(eva);
}
}
EvalValue eva = tmp->pop();
delete tmp;
delete reveral;
return eva.value;
}
int Evaluator::GetCharOp(char Ch)
{
switch (Ch) {
case '(': return OPAREN;
case ')': return CPAREN;
case '^': return EXP;
case '*': return MULT;
case '/': return DIV;
case '+': return PLUS;
case '-': return MINUS;
default: return UNKNOW;
}
}
bool Evaluator::IsDigit(char Ch)
{
if (Ch >= '0' && Ch <= '9')
{
return true;
}
return false;
}
int Evaluator::Digit(char Ch)
{
return Ch - '0';
}
void Evaluator::CheckOp(int op)
{
switch (op) {
case OPAREN:
OpStack->push(EvalValue(0, op));
break;
case CPAREN:
//出栈计算
this->openFlagEval();
break;
case EXP:
case MULT:
case DIV:
case PLUS:
case MINUS:
//优先级
this->orderOpEval(op);
break;
default:
break;
}
}
void Evaluator::openFlagEval()
{
EvalValue ev = OpStack->pop();
while (ev.opType != OPAREN)
{
PostFixStack->push(ev);
ev = OpStack->pop();
}
}
void Evaluator::orderOpEval(int op)
{
if (!OpStack->isEmpty())
{
EvalValue ev = OpStack->top();
//栈顶优先级高
while (this->checkOpOrder(ev.opType, op))
{
PostFixStack->push(OpStack->pop());
}
}
OpStack->push(EvalValue(0, op));
}
bool Evaluator::checkOpOrder(int TopOp, int op)
{
if (TopOp < op)
{
if (TopOp == EXP || // ^悠闲级高
(TopOp == MULT && op < DIV)) // * / 大于 + - 优先级
{
return true;
}
}
return false;
}
void Evaluator::EvalResult()
{
while (!OpStack->isEmpty())
{
PostFixStack->push(OpStack->pop());
}
}
string Evaluator::getOpString(int op)
{
switch (op) {
case OPAREN: return "(";
case CPAREN: return ")";
case EXP: return "^";
case MULT: return "*";
case DIV: return "/";
case PLUS: return "+";
case MINUS: return "-";
default:
break;
}
return "[error]";
}
#include
int Evaluator::CacluateWithValue(int op, int v1, int v2)
{
switch (op) {
case EXP: return pow(v2, v1);
case MULT: return v2 * v1;
case DIV: return v2 / v1;
case PLUS: return v2 + v1;
case MINUS: return v2 - v1;
default:
break;
}
return 0;
}
#endif