The application of the stack is very extensive, and the original book only explains the expression evaluation, then I will write these. In fact, the biggest use of the stack is to solve the backchainable problem, which also contains digestion recursive; and when you use stacks to resolve the backtracking problem, you rarely think of recursive, such as maze solving. In addition, people's habits are also the mainstay, such as the traversal of the tree, starting from learning, is a recursive algorithm, although the book also teaches the method of re-implementing, but when it is applied, you first thought about it; of course; If the language itself does not support recursion (such as Basic), the stack is the only choice - it seems that the current senior language is supported.
The following is the definition and implementation of the expression class, the expression can be a prefix representation, which is a suffix representation, and the TYPE distinguished by the head node data field, here is a point in which I originally written due to the assignment function of the single-link table. There is no copy of the head node, so if you assign a value between the two expressions, the information in the header node is lost. You can rewrite the assignment function of single-strand tables to solve this hidden danger, or you are not assigned between two expressions.
#ifndef expression_h
#define expression_h
#include "list.h"
#include "stack.h"
#define infix 0
#define postfix 1
#define opND 4
#define Optr 8
Template
{
PUBLIC:
INT TYPE;
Union {type opnd; char optr;};
EXPNODE (): Type (Infix), Optr ('=') {}
EXPNODE (TYPND): TYPE (OPND), OPND (OPND) {}
ExpNode (Char Optr): Type (OPTR), Optr (OPTR) {}
}
Template
{
PUBLIC:
Void input ()
{
Makeempty (); get () -> type = infix;
COUT << Endl << "Input expression, with = end input" << endl;
TYPE OPND; CHAR OPTR = '';
While (Optr! = '=')
{
CIN >> OPND;
IF (OPND! = 0)
{
EXPNODE
LastInsert (newopnd);
}
CIN >> OPTR;
ExpNode
LastInsert (Newoptr);
}
}
Void print ()
{
First ();
Cout << Endl;
For (expnode
{
Switch (P-> Type)
{
Case Opnd:
Cout << p-> opnd; Break;
Case Optr:
Cout << p-> optr; breaf;
DEFAULT: BREAK;
}
Cout << '';
}
Cout << Endl;
}
Expression & Postfix () // Transitions the expiration of the expression into a suffix expression
{
First ();
IF (GET () -> Type == Postfix) Return * this;
Stack
Expression Temp;
EXPNODE
While (p! = null)
{
Switch (P-> Type)
{
Case Opnd:
Temp.lastInsert (* p); p = next (); Break;
Case Optr:
While (ISP (S.Gettop ())> ICP (P-> OPTR))
{
EXPNODE
Temp.lastInsert (Newoptr);
}
IF (ISP (S.Gettop ()) == ICP (P-> OPTR))
{
S.POP (); p = next (); Break;
}
S.push (p-> optr); p = next (); Break;
DEFAULT: BREAK;
}
}
* this = TEMP;
Pgetfirst () -> Data.Type = Postfix;
Return * this;
}
TYPE CALCULATE ()
{
Expression Temp = * this;
IF (pgetfirst () -> data.type! = postfix) TEMP.POSTFIX ();
Stack
For (expnode
{
Switch (P-> Type)
{
Case Opnd:
S.PUSH (P-> OPND); BREAK;
Case Optr:
Right = s.POP (); left = s.pop ();
Switch (P-> OPTR)
{
Case ' ': S.Push (Left Right); Break;
Case '-': s.push (left - right); Break;
Case '*': s.push (left * right); Break;
Case '/': if (right! = 0) s.push (left / right); else return 0; Break;
// case '%': if (Right! = 0) s.push (left% right); Else Return 0; Break;
// case '^': S.Push (Power (LEFT, RIGHT)); BREAK;
DEFAULT: BREAK;
}
DEFAULT: BREAK;
}
}
Return S.POP ();
}
Private:
INT ISP (Char Optr)
{
Switch (OPTR)
{
Case '=': Return 0;
Case '(') (')
Case '^': Return 7; Case '*': Return 5;
Case '/': return 5;
Case '%': Return 5;
Case ' ': return 3;
Case '-': return 3;
Case ')': Return 8;
DEFAULT: RETURN 0;
}
}
INT ICP (Char Optr)
{
Switch (OPTR)
{
Case '=': Return 0;
Case '(': returno 8;
Case '^': return 6;
Case '*': return 4;
Case '/': return 4;
Case '%': Return 4;
Case ' ': Return 2;
Case '-': return 2;
Case ')': Return 1;
DEFAULT: RETURN 0;
}
}
}
#ENDIF
A few description
l Expression is stored with single-chain tables, you can see that there are both operands in this list, if you have seen me "How to chain into different types of objects in a list", the method here is also Supplement of article articles.
l When entering an expression, the original content will be emptied, and you must indicate input according to the prefix. If you look back, you will find that in addition to parentheses, the expression structure is "operand", "operator", "operand", ... "operator (=)", for unity This law, but also in order to make the input function simple, the brackets must be input "0 (", ") 0"; so that "0" can not appear as an operand in the expression. Because I didn't add a fault-tolerant statement in the input function, once I lost the wrong, the program was "dead".
l The process of evaluating the expression of the expression is, first turn into a suffix representation, then use the suffix to be evaluated. Because the original book explains these two algorithms, and use these two algorithms to complete the evaluation of the infix expression, I have no direct evaluation algorithm for the expression. Specific algorithm means that I will not be nonsense.
l Calculate () Note Two rows, "%" is because only the "^" Power () function is not completed only for integer expressions.
l ISP (), ICP () return value, the original book is not fine, I will say two words. The exterior priority outside the stack in the stack of '=' (Expression start and end flag) is the lowest. '(The highest in the stack, the kept the kept in the mainstay.') 'The stack is the lowest, no in the stack. The '^' Stack The highest in the stack, and the stack is low in the stack. The '× ÷%' Stack is lower than the '^' stack, and the stack is low in the stack. The ' -' Stack is lower than the '×' stack, and the stack is lower than the stack. In this way, it is integrated, there are 9 priorities, so I have drawn the table on the book.