- 浏览: 84598 次
文章分类
最新评论
-
bailangfei3344:
自我介绍 -
regionwar:
你好,转化为人为:1、不该加锁的不要加锁:局部变量,单线程占用 ...
关于java锁机制的优化 -
danni505:
希望能交流:
msn:danni-505#hotmail.co ...
关于java锁机制的优化 -
ouspec:
收藏的东西不错。
TOP500 -
willpower:
The idea behind is e-sync IO do ...
Rethink the sync
Expressions, Conversion and Evaluation with C
(All you need to know about Expressions)
In this tutorial, I will be writing in detail about an important programming concept i.e. Algebraic Expressions, different expression notations like Prefix, Postfix and Infix evaluation of the expressions, how to convert an expression from one notation to another and how to evaluate Algebraic Expressions using computers.
Each and every concept is backed by algorithms, illustrative examples and programs in C to help new programmers understand the concepts more clearly.
We will be using the concepts of Stacks and Binary Trees to convert and evaluate the expressions, so the reader is required to be clear with the fundamentals of these concepts.
Topics covered by this tutorial:
- What is an Algebraic Expression?
- What are different notations of representing expressions like Infix, Prefix, and Postfix?
- Why do we need different notations for the same expression?
- Why do we need to convert the expressions from one notation to another?
- How can we convert the expressions from one notation to another? (Algorithms, Programs, examples)
- Expression Trees
- How can we evaluate an expression? (Algorithm, Program)
- Reader's Exercise.
Algebraic Expressions, an Introduction:
An algebraic expression is a legal combination of operands and operators. Operand is the quantity (unit of data) on which a mathematical operation is performed. Operand may be a variable like x, y, z or a constant like 5, 4,0,9,1 etc. Operator is a symbol which signifies a mathematical or logical operation between the operands. Example of familiar operators include +,-,*, /, ^ ( throughout the tutorial '^' will be referred to as Exponential Operator ) etc. Considering these definitions of operands and operators now we can write an example of expression as x+y*z. Note the phrase "LEGAL combination" in the definition of an Algebraic Expression, in aforementioned example of expression x+y*z, the operands x , y, z and the operators +,* form some legal combination. Take another example +xyz*, in this expression operators and operands do not make any LEGAL combination; this expression is not a valid algebraic expression.
An Algebraic Expression can be represented using three different notations:
INFIX: From our school times we have been familiar with the expressions in which operands surround the operator, e.g. x+y, 6*3 etc this way of writing the Expressions is called infix notation.
PREFIX: Prefix notation also Known as Polish notation, is a symbolic logic invented by Polish mathematician Jan Lukasiewicz in the 1920's. In the prefix notation, as the name only suggests, operator comes before the operands, e.g. +xy, *+xyz etc.
POSTFIX: Postfix notation is also Known as Reverse Polish notation. They are different from the infix and prefix notations in the sense that in the postfix notation, the operator comes after the operands, e.g. xy+, xyz+* etc.
Now, the obvious question that comes in our mind is, Why use these weird looking PREFIX and POSTFIX notations when we have a sweet and simple INFIX notation?
To our surprise INFIX notations are not as simple as they seem specially while evaluating them. To evaluate an infix expression we need to consider Operators' Priority and Associativity.
For example, will expression 3+5*4 evaluate to 32 i.e. (3+5)*4 or to 23 i.e. 3+(5*4). To solve this problem Precedence or Priority of the operators were defined. Operator precedence governs evaluation order. An operator with higher precedence is applied before an operator with lower precedence.
Following figure shows operator Precedence in descending order.
Now, as we know the precedence of the operators, we can evaluate the expression 3+5*4 as 23. But wait, it doesn't end here what about the expression 6/3*2? Will this expression evaluate to 4 i.e. (6/3)*2 or to 1 i.e. 6/(3*2).As both * and the / have same priorities, to solve this conflict, we now need to use Associativity of the operators. Operator Associativity governs the evaluation order of the operators of same priority. For an operator with left-Associativity, evaluation is from left to right and for an operator with right-Associativity; evaluation is from right to left.
*, /, +, - have left Associativity. So the expression will evaluate to 4 and not 1.
N.B: We use Associativity of the operators only to resolve conflict between operators of same priority.
Due to the above mentioned problem of considering operators' Priority and Associativity while evaluating an expression using infix notation, we use prefix and postfix notations. Both prefix and postfix notations have an advantage over infix that while evaluating an expression in prefix or postfix form we need not consider the Priority and Associativity of the operators. E.g. x/y*z becomes */xyz in prefix and xy/z* in postfix. Both prefix and postfix notations make Expression Evaluation a lot easier. (we will discuss this in detail, later in this tutorial)
But it is not easy to remember and manually write expressions in prefix or postfix form e.g. which one of following equations is easy to remember (x+y)/z*a (Infix) or xy+z/a* (Postfix)?
So, what is actually done is that the expression is scanned from the user in infix form; it is converted into prefix or postfix form and then evaluated without considering the parenthesis and priority of the operators.
Now let us move on the programming part, How to convert an expression from one notation to another? Well there are two ways to convert expression from one notation to another. First one uses Stack and second method uses Expression trees.
As there are 3 notations namely prefix, infix and postfix , there are a total of 6 conversions that can be done ,i.e. infix -> prefix, infix -> postfix, prefix -> infix, prefix -> postfix, postfix -> prefix, postfix -> infix. For the first 2 conversions we will be using stacks and for remaining 4 conversions we will be using Binary Expression Trees.
To convert an expression from infix to prefix and postfix, we are going to use stacks. Those who do not know what a stack is, here are a few words about it. A stack is a special type of data structure in which items are removed in reverse order from which they are added. Stack follows Last In First Out (LIFO) pattern. Adding an element to a stack is called PUSH and removing an item from a stack is called POP.
Converting Expression from Infix to Postfix using STACK
To convert an expression from infix to postfix, we are going to use a stack.
Algorithm
1) Examine the next element in the input.
2) If it is an operand, output it.
3) If it is opening parenthesis, push it on stack.
4) If it is an operator, then
i) If stack is empty, push operator on stack.
ii) If the top of the stack is opening parenthesis, push operator on stack.
iii) If it has higher priority than the top of stack, push operator on stack.
iv) Else pop the operator from the stack and output it, repeat step 4.
5) If it is a closing parenthesis, pop operators from the stack and output them until an opening parenthesis is encountered. pop and discard the opening parenthesis.
6) If there is more input go to step 1
7) If there is no more input, unstack the remaining operators to output.
Example
Suppose we want to convert 2*3/(2-1)+5*(4-1) into Prefix form: Reversed Expression: )1-4(*5+)1-2(/3*2
Char Scanned | Stack Contents(Top on right) | Postfix Expression |
2 | Empty | 2 |
* | * | 2 |
3 | * | 23 |
/ | / | 23* |
( | /( | 23* |
2 | /( | 23*2 |
- | /(- | 23*2 |
1 | /(- | 23*21 |
) | / | 23*21- |
+ | + | 23*21-/ |
5 | + | 23*21-/5 |
* | +* | 23*21-/5 |
( | +*( | 23*21-/5 |
4 | +*( | 23*21-/54 |
- | +*(- | 23*21-/54 |
1 | +*(- | 23*21-/541 |
) | +* | 23*21-/541- |
Empty | 23*21-/541-*+ |
So, the Postfix Expression is 23*21-/541-*+
Refer program #1 for infix to postfix Conversion
Converting Expression from Infix to Prefix using STACK
It is a bit trickier algorithm, in this algorithm we first reverse the input expression so that a+b*c will become c*b+a and then we do the conversion and then again the output string is reversed. Doing this has an advantage that except for some minor modifications the algorithm for Infix->Prefix remains almost same as the one for Infix->Postfix.
Algorithm
1) Reverse the input string.
2) Examine the next element in the input.
3) If it is operand, add it to output string.
4) If it is Closing parenthesis, push it on stack.
5) If it is an operator, then
i) If stack is empty, push operator on stack.
ii) If the top of stack is closing parenthesis, push operator on stack.
iii) If it has same or higher priority than the top of stack, push operator on stack.
iv) Else pop the operator from the stack and add it to output string, repeat step 5.
6) If it is a opening parenthesis, pop operators from stack and add them to output string until a closing parenthesis is encountered. Pop and discard the closing parenthesis.
7) If there is more input go to step 2
8) If there is no more input, unstack the remaining operators and add them to output string.
9) Reverse the output string.
Example
Suppose we want to convert 2*3/(2-1)+5*(4-1) into Prefix form: Reversed Expression: )1-4(*5+)1-2(/3*2
Char Scanned | Stack Contents(Top on right) | Prefix Expression(right to left) |
) | ) | |
1 | ) | 1 |
- | )- | 1 |
4 | )- | 14 |
( | Empty | 14- |
* | * | 14- |
5 | * | 14-5 |
+ | + | 14-5* |
) | +) | 14-5* |
1 | +) | 14-5*1 |
- | +)- | 14-5*1 |
2 | +)- | 14-5*12 |
( | + | 14-5*12- |
/ | +/ | 14-5*12- |
3 | +/ | 14-5*12-3 |
* | +/* | 14-5*12-3 |
2 | +/* | 14-5*12-32 |
Empty | 14-5*12-32*/+ |
Reverse the output string : +/*23-21*5-41 So, the final Prefix Expression is +/*23-21*5-41
Refer program #1 For infix to prefix Conversion.
Remaining Conversions
All the remaining conversions can easily be done using a Binary Expressions Tree. In fact the above 2 conversions, viz Infix-> Prefix and Infix -> Postfix, can also be done using Binary Expression Trees but that is a very tricky thing and stacks can be used to handle the conversions easily. Now we will move a step ahead and define a Binary Expression Tree.
Binary Expression Tree
An Expression Tree is a strictly binary tree in which leaf nodes contain Operands and non-leaf nodes contain Operator, root node contain the operator that is applied to result of left and right sub trees. Once we obtain the Expression Tree for a particular expression, its conversion into different notations (infix, prefix, and postfix) and evaluation become a matter of Traversing the Expression Tree. The following Figure shows an expression tree for above expression 2*3/(2-1)+5*(4-1)
N.B. A binary expression tree does not contain parenthesis, the reason for this is that for evaluating an expression using expression tree, structure of tree itself decides order of the operations.
When we run Pre-order traversal (visit root, left child and then right child) on the Binary Expression Tree we get prefix notation of the expression, similarly an Post-order traversal (visit left child, right child and then root) will yield postfix notation. What will we get from an in-order Traversal (visit left child, root and then right child)? Well, for the expressions which do not contain parenthesis, in-order traversal will definitely give infix notation of expression but expressions whose infix form requires parenthesis to override conventional precedence of operators can not be retrieved by simple in-order traversal.
Doing the Conversions with Expression Trees
Prefix -> Infix
The following algorithm works for the expressions whose infix form does not require parenthesis to override conventional precedence of operators. 1) Create the Expression Tree from the prefix expression
2) Run in-order traversal on the tree.
Prefix -> Postfix
1) Create the Expression Tree from the prefix expression
2) Run post-order traversal on the tree.
Well you see how easy it is! Most important point here is to create Expression tree from Prefix expression, following algorithm does that for you:
Algorithm for creating Expression Tree from a Prefix Expression
1) Reverse the prefix expression
2) Examine the next element in the input.
3) If it is operand then
i) create a leaf node i.e. node having no child (node- >left_child=node->right_child=NULL)
ii) copy the operand in data part
iii) PUSH node's address on stack
4) If it is an operator, then
i) create a node
ii) copy the operator in data part
iii) POP address of node from stack and assign it to node->left_child
iv) POP address of node from stack and assign it to node->right_child
v) PUSH node's address on stack
5) If there is more input go to step 2
6) If there is no more input, POP the address from stack, which is the address of the ROOT node of Expression Tree.
Refer program #2 For prefix to infix and postfix conversion.
Postfix -> Infix
The following algorithm works for the expressions whose infix form does not require parenthesis to override conventional precedence of operators. 1) Create the Expression Tree from the postfix expression 2) Run in-order traversal on the tree.
Postfix -> Prefix
1) Create the Expression Tree from the postfix expression 2) Run pre-order traversal on the tree.
Algorithm for creating Expression Tree from a Postfix Expression
1) Examine the next element in the input.
2) If it is operand then
i) create a leaf node i.e. node having no child (node->left_child=node->left_child=NULL)
ii) copy the operand in data part
iii) PUSH node's address on stack
3) If it is an operator, then
i) create a node
ii) copy the operator in data part
iii) POP address of node from stack and assign it to node->right_child
iv) POP address of node from stack and assign it to node->left_child
v) PUSH node's address on stack
4) If there is more input go to step 1
5) If there is no more input, POP the address from stack, which is the address of the ROOT node of Expression Tree.
Refer program #2 For postfix to infix and prefix conversion.
Well, at last we are done with converting the expressions from one type to another. As a summary here is what we have done so far : 1) Infix -> Prefix using stack
2) Infix -> Postfix using stack
3) Prefix -> Infix using Expression Trees
4) Prefix -> Postfix using Expression Trees
5) Postfix -> Infix using Expression Trees
6) Postfix -> Prefix using Expression Trees
Now all we are left with is Evaluating an Expression. Evaluating an expression involves two phases: 1) Create an expression tree for given expression
2) Evaluate the tree recursively
We already know how to create an expression tree for prefix and postfix notations. Algorithm for creating Expression Tree from Infix expression is left as reader exercise and some help can be found at http://www.seas.gwu.edu/~csci131/fall96/exp_to_tree.html
Following procedure will evaluate an expression tree in a recursive fashion:
Procedure Name: Evaluate Tree Arguments : Address of root of the tree int Evaluate Tree (struct node* root)
IF root != NULL IF current node contains an operator x = Evaluate Tree(root -> left_child) y = Evaluate Tree(root -> right_child) Perform operation on x and y, specified by the operator and store result in z Return z else Return root->data
Refer program #2 for evaluation of an Expression Tree.
发表评论
-
字符编码笔记:ASCII,Unicode和UTF-8 (引用)
2009-01-07 10:39 913字符编码笔记:ASCII,Unicode和UTF-8 阮一峰 ... -
How to set up a simple LRU cache using LinkedHash
2008-11-03 18:05 1275How to set up a simple LRU cach ... -
Scalability?
2008-10-07 14:07 820严格上讲,scalability还没有正式定义, 甚至有人觉得 ... -
Cray Reminiscences
2007-08-29 15:54 785Kirk Pepperdine's attendence of ... -
lock-free
2007-06-18 22:06 9861. http://www.ibm.com/developer ... -
解决java.lang.OutOfMemoryError: PermGen space(转帖)
2007-06-05 18:07 3156解决方案就是:在启动服务器时加上指定PermGen区域的内存大 ... -
Performance...
2007-06-05 15:11 973« I used to work for... | Mai ... -
数据仓库
2007-04-18 10:38 1113... -
Java cleanup code
2007-04-03 12:20 1291Java shutdown hook guarantee th ... -
Java performance tunning
2007-04-03 11:37 930http://www.javaperformancetunin ... -
Running IE from command line
2007-04-03 10:58 1103Here's a simple way you can ru ... -
Unicode and UTF8
2007-04-03 10:27 904What is Unicode? Unicode provid ... -
Daemon Thread Notes
2007-04-03 09:16 26441. 只要程式中的non-Daemon thread都結束了. ... -
How to know the main class of a jar file?
2007-04-02 15:18 1023Easy. Here is an implementation ... -
The best chinese BAT tutorial(from www.boofee.net/bigfee/)
2007-03-27 11:58 1325如何创建批处理文件? 不要听了批处理文件就感到很神气 ... -
Basics - Binary search
2007-03-26 15:53 963java 代码 public class Bin ... -
MergeSort
2007-03-23 17:26 824MergeSort is a sample solutio ... -
Graph data structure
2007-03-23 12:04 8721. adjacent matrix good for bor ... -
Functional Programming For The Rest of Us
2007-03-23 10:39 1264I like connect beautiful artic ... -
Functional Programming For The Rest of Us
2007-03-23 10:24 1058I like connect beautiful artic ...
相关推荐
You will learn how to match, extract, and transform text by matching specific words, characters, and patterns. You will learn when and where to apply the methods for finding patterns in digits, ...
安装$ yarn add --dev babel-plugin-transform-replace-expressions例输入文件: const env = process . env . NODE_ENV ;typeof Hello === "number" ; .babelrc : { " plugins " : [ [ " babel-plugin-transform-...
do-expressions":r(206),"transform-es2015-arrow-functions":r(68),"transform-es2015-block-scoped-functions":r(69),"transform-es2015-block-scoping":r(70),"transform-es2015-classes":r(71),"transform-es...
本篇文章将深入探讨Babel插件`transform-react-jsx-location`以及它是如何将JSX代码的位置信息插入到DOM中的。 首先,`transform-react-jsx`是Babel的一个核心插件,它的主要任务是将JSX元素转换为React....
We propose a method for exaggerating facial expressions derived from exaggeration mappings that transform facial motions into exaggerated motions. The exaggeration mapping of facial motions is defined...
Fast Fourier Transform Section 9.10. A Unification Algorithm Section 9.11. Multitasking with Engines <br>Bibliography <br>Answers to Selected Exercises <br>Formal Syntax of Scheme...
Become familiar with immutable data structures and easily transform them with type-safe and declarative operations Create custom infix operators to simplify existing operations or even to start your ...
Example-laden chapters include both versions 1.0 and 2.0 features and demonstrate how to transform one XML data format to another. The book covers the key structural elements of an XSLT file and ...
在Expressions in use(表达用法)部分,课件可能会提供一些常用的短语和句型,让学生在实际语境中学习和使用,比如"response"、"adopt"和"focus"等词构成的不同表达,如"I haven’t gotten a(n) response yet." 和...
• Offers developers powerful LINQ query expressions to perform virtually any data-related task • Teaches how to query SQL databases for objects and how to modify those objects • Demonstrates ...
* 文件中选择了多种词汇,如常用词汇、专业词汇、 idiomatic expressions等,例如“slip v. 滑动,滑落;忽略”中使用了常用词汇。 * 词汇选择也考虑了词汇的词性、词义和使用场景,例如“spit v. 吐(唾液等);唾弃”...
Chapter 3, Expressing Anonymous Methods with Lambda Expressions, walks us through the concept of delegates and uses it to create and use an anonymous method. After we dig through the anonymous method,...
在开发Oracle OLAP应用时,首先需要进行数据源的准备,这可能涉及到ETL(Extract, Transform, Load)过程,将原始数据清洗、转换并加载到多维数据结构中。接着,设计和构建立方体,定义维度和度量,以及层次结构...
- **Expressions (表达式)**:编写和编辑用于控制对象行为的数学表达式。 - **Constraints (约束)**:管理和编辑对象之间的约束关系。 - **Rigid Bodies (刚体)**:管理和编辑刚体模拟的对象。 **5. Select ...
Preferences API Ref Objects Reflection Regular Expressions Versioning Zip Instrument Java Virtual Machine Java HotspotTM Client VM Java HotspotTM Server VM Platforms SolarisTM Linux Windows ...
在数据加载与更新方面,Oracle OLAP支持多种数据源,如关系数据库、文本文件等,通过ETL(Extract, Transform, Load)过程将数据导入到OLAP立方体中。10g Release 2版本增强了数据装载的性能,同时提供了自动化的...
ETL(Extract, Transform, Load)是数据仓库构建的核心过程。它从多个源系统抽取数据,对数据进行清洗、转换,然后加载到数据仓库中。微软提供了SSIS(SQL Server Integration Services)作为ETL工具,支持复杂的...
3. **折叠表达式(Fold Expressions)**:这是一种新的语法结构,用于简化元编程中的展开操作,特别是在模板和运算符重载中非常有用。 4. **`if constexpr`**:这是一种条件编译的改进,允许在编译时判断分支,只有...
数据仓库的开发通常涉及到大量的ETL(Extract, Transform, Load)过程,其中SQL用于从源头抽取数据,转换数据格式,并加载到目标仓库中。 第四章“OLAP(Online Analytical Processing)技术”介绍的是SQL在多维...