Download Chapter 25 Java Data Structures

Document related concepts

Quadtree wikipedia , lookup

Binary search tree wikipedia , lookup

B-tree wikipedia , lookup

Array data structure wikipedia , lookup

Linked list wikipedia , lookup

Transcript
Chapter 24
Implementing
Lists, Stacks, Queues,
and
Priority Queues
CIS265/506 Cleveland State University – Prof. Victor Matos
Adapted from: Introduction to Java Programming: Comprehensive Version, Eighth Edition by Y. Daniel Liang
Objectives
1.
2.
3.
4.
5.
6.
2
To design a list with interface and abstract class (§24.2).
To design and implement a dynamic list using an array (§24.3).
To design and implement a dynamic list using a linked structure (§24.4).
To design and implement a stack using an array list (§24.5).
To design and implement a queue using a linked list (§24.6).
To evaluate expressions using stacks (§24.7).
What is a Data Structure?
 A data structure is a collection of data organized in some fashion.
 A data structure not only stores data, but also supports the
operations for manipulating data in the structure.
For example:
 An array is a data structure that holds a collection of data in sequential
order.
 You can find the size of the array, store, retrieve, and modify data in the
array.
 Array is simple and easy to use, but it has some limitations: …
3
Limitations of arrays
•
Once an array is created, its size cannot be altered.
•
Array provides inadequate support for:
•
•
•
•
4
inserting,
deleting,
sorting, and
searching operations.
Object-Oriented Data Structure
A data structure can be consider as a container object or a collection object.
To define a data structure is similar to declare a class.
The class for a data structure should
1.
use data fields to store data and
2.
provide methods to support operations such as insertion
and deletion.
5
Four Classic Data Structures
Four classic dynamic data structures are lists, stacks, queues, and binary trees.
6
1.
A list is a collection of data stored sequentially. It supports insertion and
deletion anywhere in the list.
2.
A stack can be perceived as a special type of the list where insertions and
deletions take place only at the one end, referred to as the top of a stack.
3.
A queue represents a waiting list, where insertions take place at the back
(also referred to as the tail of) of a queue and deletions take place from the
front (also referred to as the head of) of a queue.
4.
A binary tree is a data structure in which each data item has one direct
ancestor and up to two descendants.
Lists
A list is a common data structure to store data in sequential order.
Operations on a list are usually the following:
·
·
·
·
·
·
7
Retrieve an element from this list.
Insert a new element to this list.
Delete an element from this list.
Find how many elements are in this list.
Find if an element is in this list.
Find if this list is empty.
Two Ways to Implement Lists
8
1.
Use an array to store the elements. The array is dynamically
created. If the capacity of the array is exceeded, create a new larger
array and copy all the elements from the current array to the new
array.
2.
Use a linked structure. A linked structure consists of nodes.
Each node is dynamically created to hold an element. All the nodes
are linked together to form a list.
Design of ArrayList and LinkedList
For convenience, let’s name these two classes: MyArrayList and
MyLinkedList. These two classes have common operations, but different
data fields.
Their common operations can be generalized in an interface or an abstract
class. Such an abstract class is known as a convenience class.
MyArrayList
MyList
MyAbstractList
MyLinkedList
9
MyList Interface and MyAbstractList Class
«interface»
MyList<E>
+add(e: E) : void
Appends a new element at the end of this list.
+add(index: int, e: E) : void
Adds a new element at the specified index in this list.
+clear(): void
Removes all the elements from this list.
+contains(e: E): boolean
Returns true if this list contains the element.
+get(index: int) : E
Returns the element from this list at the specified index.
+indexOf(e: E) : int
Returns the index of the first matching element in this list.
+isEmpty(): boolean
Returns true if this list contains no elements.
+lastIndexOf(e: E) : int
Returns the index of the last matching element in this list.
+remove(e: E): boolean
Removes the element from this list.
+size(): int
Returns the number of elements in this list.
+remove(index: int) : E
Removes the element at the specified index and returns the
removed element.
+set(index: int, e: E) : E
Sets the element at the specified index and returns the
element you are replacing.
MyAbstractList<E>
10
#size: int
The size of the list.
#MyAbstractList()
Creates a default list.
#MyAbstractList(objects: E[])
Creates a list from an array of objects.
+add(e: E) : void
Implements the add method.
+isEmpty(): boolean
Implements the isEmpty method.
+size(): int
Implements the size method.
+remove(e: E): boolean
Implements the remove method.
MyList Interface
public interface MyList<E> {
/** Add a new element at the end of this list */
public void add(E e);
/** Add a new element at the specified index in this list */
public void add(int index, E e);
/** Clear the list */
public void clear();
/** Return true if this list contains the element */
public boolean contains(E e);
/** Return the element from this list at the specified index */
public E get(int index);
/** Return the index of the first matching element in this list.
public int indexOf(E e);
Return -1 if no match. */
/** Return true if this list contains no elements */
public boolean isEmpty();
/** Return the index of the last matching element in this list. Return -1 if no match. */
public int lastIndexOf(E e);
/** Remove the first occurrence of the element o from this list.
* Shift any subsequent elements to the left.
* Return true if the element is removed. */
public boolean remove(E e);
/** Remove the element at the specified position in this list
* Shift any subsequent elements to the left.
* Return the element that was removed from the list. */
public E remove(int index);
/** Replace the element at the specified position in this list
* with the specified element and returns the new set. */
public Object set(int index, E e);
/** Return the number of elements in this list */
public int size();
11}
MyAbstractList Class
public abstract class MyAbstractList<E> implements MyList<E> {
protected int size = 0; // The size of the list
/** Create a default list */
protected MyAbstractList() {
}
/** Create a list from an array of objects */
protected MyAbstractList(E[] objects) {
for (int i = 0; i < objects.length; i++)
add(objects[i]);
}
/** Add a new element at the end of this list */
public void add(E e) {
add(size, e);
}
/** Return true if this list contains no elements */
public boolean isEmpty() {
return size == 0;
}
/** Return the number of elements in this list */
public int size() {
return size;
}
/** Remove the first occurrence of the element o from this list.
* Shift any subsequent elements to the left.
* Return true if the element is removed. */
public boolean remove(E e) {
if (indexOf(e) >= 0) {
remove(indexOf(e));
return true;
}
else
return false;
}
12}
Array Lists
Array is a fixed-size data structure. Once an array is created, its
size cannot be changed.
You can still use array to implement dynamic data structures. The
trick is to create a new larger array to replace the current array if the
current array cannot hold new elements in the list.
1.
2.
3.
13
Initially, an array, say data of ObjectType[], is created with a default size.
When inserting a new element into the array, first ensure there is enough
room in the array.
If not, create a new array with the size as twice as the current one. Copy the
elements from the current array to the new array. The new array now
becomes the current array.
Array List Animation
www.cs.armstrong.edu/liang/animation/ArrayListAnimation.html
14
Insertion
Before inserting a new element at a specified index, shift all the elements after
the index to the right and increase the list size by 1.
Before inserting
e at insertion point i
0
e0 e1
e
After inserting
e at insertion point i,
list size is
incremented by 1
1
…
i
… ei-1 ei
i+1 …
k-1 k
…
ek-1 ek
ei+1
Insertion point
0
1
e 0 e1
…
i
… ei-1 e
i+1 i+2 …
ei
e inserted here
15
data.length -1
…shift…
ei+1
…
k
k+1
ek-1 ek
data.length -1
Deletion
To remove an element at a specified index, shift all the elements after the
index to the left by one position and decrease the list size by 1.
Before deleting the
element at index i
0
1
e0 e1
…
i
… ei-1 ei
Delete this element
After deleting the
element, list size is
decremented by 1
0
1
e 0 e1
…
i
… ei-1 ei+1
i+1 …
k-1 k
…
ek-1 ek
ei+1
…shift…
…
…
data.length -1
k-2 k-1
ek-1 ek
data.length -1
16
Implementing MyArrayList
MyAbstractList<E>
MyArrayList<E>
-data: E[]
+MyArrayList()
Creates a default array list.
+MyArrayList(objects: E[])
Creates an array list from an array of objects.
-ensureCapacity(): void
Doubles the current array size if needed.
17
Implementing MyArrayList
public class MyArrayList<E> extends MyAbstractList<E> {
public static final int INITIAL_CAPACITY = 16;
private E[] data = (E[])new Object[INITIAL_CAPACITY];
/** Create a default list */
public MyArrayList() {
}
/** Create a list from an array of objects */
public MyArrayList(E[] objects) {
for (int i = 0; i < objects.length; i++)
add(objects[i]); // Warning: don’t use super(objects)!
}
/** Add a new element at the specified index in this list */
public void add(int index, E e) {
ensureCapacity();
// Move the elements to the right after the specified index
for (int i = size - 1; i >= index; i--)
data[i + 1] = data[i];
// Insert new element to data[index]
data[index] = e;
18 }
// Increase size by 1
size++;
Implementing MyArrayList
/** Create a new larger array, double the current size */
private void ensureCapacity() {
if (size >= data.length) {
E[] newData = (E[])(new Object[size * 2 + 1]);
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
}
/** Clear the list */
public void clear() {
data = (E[])new Object[INITIAL_CAPACITY];
size = 0;
}
19
Implementing MyArrayList
cont. 2/4
/** Remove the element at the specified position in this list
* Shift any subsequent elements to the left.
* Return the element that was removed from the list. */
public E remove(int index) {
E e = data[index];
// Shift data to the left
for (int j = index; j < size - 1; j++)
data[j] = data[j + 1];
data[size - 1] = null; // This element is now null
// Decrement size
size--;
return e;
}
20
Implementing MyArrayList
cont. 3/4
// Replace element at specified position in this list with the specified element
public E set(int index, E e) {
E old = data[index];
data[index] = e;
return old;
}
/** Override toString() to return elements in the list */
public String toString() {
StringBuilder result = new StringBuilder("[");
for (int i = 0; i < size; i++) {
result.append(data[i]);
if (i < size - 1) result.append(", ");
}
return result.toString() + "]";
}
/** Trims the capacity to current size */
public void trimToSize() {
if (size != data.length) { // If size == capacity, no need to trim
E[] newData = (E[])(new Object[size]);
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
}
21}
Test MyArrayList
cont. 4/4
public class TestList {
public static void main(String[] args) {
// Create a list
MyList<String> list = new MyArrayList<String>();
// Add elements to the list
list.add("America"); // Add it to the list
System.out.println("(1) " + list);
list.add(0, "Canada"); // Add it to the beginning of the list
System.out.println("(2) " + list);
list.add("Russia"); // Add it to the end of the list
System.out.println("(3) " + list);
list.add("France"); // Add it to the end of the list
System.out.println("(4) " + list);
list.add(2, "Germany"); // Add it to the list at index 2
System.out.println("(5) " + list);
list.add(5, "Norway"); // Add it to the list at index 5
System.out.println("(6) " + list);
// Remove elements from the list
list.remove("Canada"); // Same as list.remove(0) in this case
System.out.println("(7) " + list);
list.remove(2); // Remove the element at index 2
System.out.println("(8) " + list);
list.remove(list.size() - 1); // Remove the last element
System.out.println("(9) " + list);
22
}
}
Linked Lists
Observations:
 Since MyArrayList is implemented using an array, the methods
get(int index), set(int index, Object o) and the add(Object o) for adding an
element at the end of the list are efficient.
 However, the methods add(int index, Object o) and remove(int index) are
inefficient because they require shifting potentially a large number of
elements.
 You can use a linked structure to improve efficiency for adding and
removing an element anywhere in a list.
23
Linked List Animation
www.cs.armstrong.edu/liang/animation/LinkedListAnimation.html
24
Nodes in Linked Lists
A linked list consists of nodes. Each node contains a data element, and each
node is linked to its next neighbor. Thus a node can be defined as a class, as
follows:
class Node<E> {
E
element;
Node next;
public Node(E obj) {
element = obj;
}
25
}
Adding Three Nodes
 The variable head refers to the first node in the list, and the variable tail
refers to the last node in the list.
 If the list is empty, both are null.
Example.
You can create three nodes to store three strings in a list, as follows:
Step 1: Declare head and tail:
Node<String> head = null;
Node<String> tail = null;
26
The list is empty now
Adding Three Nodes, cont.
Step 2: Create the first node and insert it to the list:
27
Adding Three Nodes, cont.
Step 3: Create the second node and insert it to the list:
28
Adding Three Nodes, cont.
Step 4: Create the third node and insert it to the list:
29
Traversing All Elements in the List
•
The last node has its next pointer data field set to null.
•
You may use the following loop to traverse all the nodes in the list.
Node<E> current = head;
while (current != null) {
System.out.println(current.element);
current = current.next;
}
30
MyLinkedList
Designing/Implementing a generic, dynamic, singly-linked list.
31
Implementing addFirst(E o)
public void addFirst(E o) {
Node<E> newNode = new Node<E>(o);
newNode.next = head;
head = newNode;
size++;
if (tail == null)
tail = head;
head
}
e0
tail
…
next
A new node
to be inserted
here
ei
ei+1
next
next
…
ek
null
element
next
(a) Before a new node is inserted.
head
tail
element
e0
next
next
New node inserted here
32
…
ei
ei+1
next
next
(b) After a new node is inserted.
…
ek
null
Implementing addLast(E o)
public void addLast(E o) {
if (tail == null) {
head = tail = new Node<E>(element);
}
else {
tail.next = new Node<E>(element);
tail = tail.next;
}
head
size++;
…
}
e0
ei
next
next
tail
ei+1
…
next
ek
null
A new node
to be inserted
here
(a) Before a new node is inserted.
o
null
head
e0
next
tail
…
ei
ei+1
next
next
(b) After a new node is inserted.
33
…
ek
o
next
null
New node inserted here
Implementing add(int index, E obj)
public void add(int index, E obj) {
if (index == 0) addFirst(obj);
else if (index >= size) addLast(obj);
else {
Node<E> current = head;
for (int i = 1; i < index; i++)
current = current.next;
Node<E> temp = current.next;
current.next = new Node<E>(obj);
(current.next).next = temp;
size++;
}
}
head
e0
current
temp
ei
ei+1
next
next
…
next
A new node
to be inserted
here
e
…
ek
null
(a) Before a new node is inserted.
null
head
e0
current
temp
ei
ei+1
next
next
…
next
A new node
is inserted in
the list
e
next
34
tail
tail
…
ek
null
(b) After a new node is inserted.
Implementing removeFirst()
public E removeFirst() {
if (size == 0) return null;
else {
Node<E> temp = head;
head = head.next;
size--;
if (head == null) tail = null;
return temp.element;
}
}
tail
head
e0
e1
next
next
…
Delete this node
ei
ei+1
next
next
…
null
(a) Before the node is deleted.
head
e1
next
tail
…
ei
ei+1
next
next
…
ek
null
(b) After the first node is deleted
35
ek
public E removeLast() {
if (size == 0) return null;
else if (size == 1)
{
Node<E> temp = head;
head = tail = null;
size = 0;
return temp.element;
}
else
{
Node<E> current = head;
for (int i = 0; i < size - 2; i++)
current = current.next;
Node temp = tail;
tail = current;
tail.next = null;
size--;
return temp.element;
}
}
36
Implementing removeLast()
current
head
e0
e1
next
next
…
ek-2
ek-1
ek
next
next
null
(a) Before the node is deleted.
Delete this node
tail
head
…
e0
e1
next
next
tail
ek-2
ek -1
next
null
(b) After the last node is deleted
Implementing remove(int index)
public E remove(int index) {
if (index < 0 || index >= size) return null;
else if (index == 0) return removeFirst();
else if (index == size - 1) return removeLast();
else {
Node<E> previous = head;
for (int i = 1; i < index; i++) {
previous = previous.next;
head
}
…
element
Node<E> current = previous.next; next
previous.next = current.next;
size--;
return current.element;
head
}
}
…
element
next
previous
current
current.next
element
element
element
next
next
next
…
element
null
Node to be deleted
(a) Before the node is deleted.
previous
current.next
element
element
next
next
(b) After the node is deleted.
37
tail
tail
…
element
null
Circular Linked Lists
A circular, singly linked list is like a singly linked list, except that the
pointer of the last node points back to the first node.
head
38
Node 1
Node 2
element
element
next
next
Node n
…
element
next
tail
Doubly Linked Lists
39

A doubly linked list contains the nodes with two pointers. One
points to the next node and the other points to the previous node.

These two pointers are conveniently called a forward pointer and a
backward pointer. So, a doubly linked list can be traversed forward and
backward.
Circular Doubly Linked Lists
A circular, doubly linked list is doubly linked list, except that
the forward pointer of the last node points to the first node and the
backward pointer of the first pointer points to the last node.
40
Stacks
A stack can be viewed as a special type of list, where the elements are
accessed, inserted, and deleted only from the end, called the top, of the
stack.
Data1
Data2
Data3
Data2
Data1
Data1
Data3
Data2
Data2
Data1
41
Data1
Data1
Data3
Data2
Data1
Queues
A queue represents a waiting list.
A queue can be viewed as a special type of list, where the elements are
inserted into the end (tail) of the queue, and are accessed and deleted
from the beginning (head) of the queue.
Data1
Data2
Data3
Data2
Data1
Data1
Data3
Data3
Data2
Data1
42
Data3
Data2
Data1
Data2
Data3
Stack Animation
www.cs.armstrong.edu/liang/animation/StackAnimation.html
43
Queue Animation
www.cs.armstrong.edu/liang/animation/QueueAnimation.html
44
Implementing Stacks and Queues
Suggestions
1. Use an array list to implement Stack
2. Use a linked list to implement Queue
 Since the insertion and deletion operations on a stack are made only at
the end of the stack, using an array list to implement a stack is more
efficient than a linked list.
 Since deletions are made at the beginning of the list, it is more efficient
to implement a queue using a linked list than an array list.
45
MyStack
This section implements a stack class using an array list and a queue
using a linked list.
MyStack
-list: MyArrayList
46
+isEmpty(): boolean
Returns true if this stack is empty.
+getSize(): int
Returns the number of elements in this stack.
+peek(): Object
Returns the top element in this stack.
+pop(): Object
Returns and removes the top element in this stack.
+push(o: Object): Object
Adds a new element to the top of this stack.
+search(o: Object): int
Returns the position of the specified element in this stack.
MyStack
public class MyStack {
private java.util.ArrayList list = new java.util.ArrayList();
public boolean isEmpty() {
return list.isEmpty();
}
public int getSize() {
return list.size();
}
public Object peek() {
return list.get(getSize() - 1);
}
public Object pop() {
Object o = list.get(getSize() - 1);
list.remove(getSize() - 1);
return o;
}
public void push(Object o) {
list.add(o);
}
public int search(Object o) {
return list.lastIndexOf(o);
}
/** Override the toString in the Object class */
public String toString() {
return "stack: " + list.toString();
}
47
}
MyQueue
Implementing a queue using a custom-made linked list.
48
MyQueue
public class MyQueue<E> {
private MyLinkedList<E> list = new MyLinkedList<E>();
public void enqueue(E e) {
list.addLast(e);
}
public E dequeue() {
return list.removeFirst();
}
public int getSize() {
return list.size();
}
public String toString() {
return "Queue: " + list.toString();
}
}
49
Example: Using Stacks and Queues
public class TestStackQueue {
public static void main(String[] args) {
// Create a stack
GenericStack<String> stack = new GenericStack<String>();
// Add elements to the stack
stack.push(“aaa"); // Push it to the stack
System.out.println("(1) " + stack);
stack.push(“bbb"); // Push it to the the stack
System.out.println("(2) " + stack);
stack.push(“ccc"); // Push it to the stack
stack.push(“ddd"); // Push it to the stack
System.out.println("(3) " + stack);
// Remove elements from
System.out.println("(4)
System.out.println("(5)
System.out.println("(6)
the
" +
" +
" +
stack
stack.pop());
stack.pop());
stack);
// Create a queue
MyQueue<String> queue = new MyQueue<String>();
// Add elements to the queue
queue.enqueue(“111"); // Add it to the queue
System.out.println("(7) " + queue);
queue.enqueue(“222"); // Add it to the queue
System.out.println("(8) " + queue);
queue.enqueue(“333"); // Add it to the queue
queue.enqueue(“444"); // Add it to the queue
System.out.println("(9) " + queue);
// Remove elements from the queue
System.out.println("(10) " + queue.dequeue());
System.out.println("(11) " + queue.dequeue());
System.out.println("(12) " + queue);
}
50
}
Priority Queue
1.
2.
3.
4.
5.
6.
A regular queue is a first-in and first-out data structure.
Elements are appended to the end of the queue and are removed from the
beginning of the queue.
In a priority queue, elements are assigned with priorities.
When accessing elements, the element with the highest priority is
removed first.
A priority queue has a largest-in, first-out behavior.
For example, the emergency room in a hospital assigns patients with
priority numbers; the patient with the highest priority is treated first.
MyPriorityQueue<E>
-heap: Heap<E>
51
+enqueue(element: E): void
Adds an element to this queue.
+dequeue(): E
Removes an element from this queue.
+getSize(): int
Returns the number of elements from this queue.
Case Study:
Using Stacks to process arithmetical expressions
Basic Definitions
There are many ways to write (and evaluate) mathematical
equations. The first, called infix notation, is what we are familiar
with from elementary school:
(5*2)-(((3+4*7)+8/6)*9)
You would evaluate this equation from right to left, taking in to
account precedence. So:
10 10 10 10 -281
53
(((3+28)+1.33)*9)
((31 + 1.33)*9)
(32.33 * 9)
291
Basic Definitions
An alternate method is postfix or Reverse Polish Notation
(RPN). The corresponding RPN equation would be:
5 2 * 3 4 7 * + 8 6 / + 9 * We’ll see how to evaluate this in a minute.
54
Example: HP-65
Type
Programmable
Introduced
1974 - MSRP $795
Calculator
Entry mode
RPN
Display Type
7-segment red LED
Display Size
10 digits
CPU
“… Like all Hewlett-Packard
calculators of the era and
most since, the HP-65
used reverse Polish notation
(RPN) and a four-level
automatic operand stack”
Processor
proprietary
Programming
Programming
language(s)
key codes
Memory
Register
8 (9) plus 4-level working stack
Program Steps 100
55
REFERENCE: http://en.wikipedia.org/wiki/HP-65
(Accessed on April 16, 2015)
Basic Definitions
•
Note that in an infix expression, the operators appear in
between the operands (1 + 2).
•
Postfix equations have the operators after the equations
(1 2 +).
•
56
In Forward Polish Notation or prefix equations, the
operators appear before the operands. The prefix form is
rarely used
(+ 1 2).
Basic Definitions
Reversed Polish Notation got its name from Jan
Lukasiewicz, a Polish mathematician, who first
published in 1951.
Lukasiewicz was a pioneer in three-valued
propositional calculus, he also was interested in
developing a parenthesis-free method of
representing logic expressions.
Today, RPN is used in many compilers and
interpreters as an intermediate form for
representing logic.
http://www-groups.dcs.st-and.ac.uk/~history/PictDisplay/Lukasiewicz.html
University of St. Andrews.
57
Examples
58
RPN expressions
Infix
Prefix
Postfix
A+B
A+B*C
A*(B+C)
A*B+C
A+B*C+D-E*F
(A+B)*(C+D-E)*F
+AB
+A*BC
*A+BC
+*ABC
-++A*BCD*EF
**+AB-+CDEF
AB+
ABC*+
ABC+*
AB*C+
ABC*+D+EF*AB+CD+E-*F*
Evaluating RPN Expressions
We evaluate RPN using a left-to-right scan.
An operator is preceded by two operands, so we store the first
operand, then the second, and once the operator arrives, we
use it to compute or evaluate the two operands we just stored.
3 5 +
Store the value 3, then the value 5, then using the + operator,
evaluate the pending calculation as 8.
59
Evaluating RPN Expressions
What happens if our equation has more than one operator? Now
we’ll need a way to store the intermediate result as well:
3 5 + 10 *
Store the 3, then 5. Evaluate with the +, getting 8.
Store the 8, then store10, when * arrives evaluate the expression
using the previous two arguments.
The final result is 80.
60
Evaluating RPN Expressions
It starts to become apparent that we apply the operator to the
last two operands we stored.
Example:
3 5 2 * -
61
•
Store the 3, then the 5, then the 2.
•
Apply the * to the 5 and 2, getting 10. Store the value 10.
•
Apply the - operator to the stored values 3 and 10 (3 - 10)
getting -7.
Evaluating RPN Expressions
Algorithm to evaluate an RPN expression
62
1.
We scan our input stream from left to right, removing the first character
as we go.
2.
We check the character to see if it is an operator or an operand.
3.
If it is an operand, we push it on the stack.
4.
If it is an operator, we remove the top two items from the stack, and
perform the requested operation.
5.
We then push the result back on the stack.
6.
If all went well, at the end of the stream, there will be only one item on
the stack - our final result.
Evaluating RPN Expressions
Step Stack
3, 5,+ 2, 4 - * 6 *
1
3
2
3
4
5
63
RPN Expression
5
3
8
2
8
5 + 2, 4 - * 6 *
+ 2, 4 - * 6 *
2, 4 - * 6 *
4-*6*
Step Stack
6
4
2
8
-2
8
7
RPN Expression
-*6*
*6*
-16
8
9
10
6*
6
-16
-96
*
Evaluating RPN Expressions
1/3
package csu.matos;
import java.util.Stack;
import java.util.StringTokenizer;
public class Driver {
public static void main(String[] args) {
// Taken from Daniel Liang – Intro to Java Prog.
// the input is a correct postfix expression
String expression = "1 2 + 3 *";
try {
System.out.println( evaluateExpression(expression) );
}
catch (Exception ex) {
System.out.println("Wrong expression");
}
}
/** Evaluate an expression **********************************************/
public static int evaluateExpression(String expression) {
// Create operandStack to store operands
Stack<Integer> operandStack = new Stack<Integer>();
64
// Extract operands and operators
StringTokenizer tokens = new StringTokenizer(expression, " +-/*%", true);
Evaluating RPN Expressions
2/3
// Phase 1: Scan tokens
while (tokens.hasMoreTokens()) {
String token = tokens.nextToken().trim(); // Extract a token
if (token.length() == 0) { // Blank space
continue; // Back to the while loop to extract the next token
}
else if (token.equals("+") || token.equals("-") ||
token.equals("*") || token.equals("/")) {
processAnOperator(token, operandStack);
}
else { // An operand scanned
// Push an operand to the stack
operandStack.push(new Integer(token));
}
}
// Return the result
return ((Integer)(operandStack.pop())).intValue();
}
65
Evaluating RPN Expressions
3/3
// Process one operator: Take an operator from operatorStack and
// apply it on the operands in the operandStack
66
public static void processAnOperator(String token, Stack operandStack) {
char op = token.chatAt(0);
if (op == '+') {
int op1 = ((Integer)(operandStack.pop())).intValue();
int op2 = ((Integer)(operandStack.pop())).intValue();
operandStack.push(new Integer(op2 + op1));
}
else if (op == '-') {
int op1 = ((Integer)(operandStack.pop())).intValue();
int op2 = ((Integer)(operandStack.pop())).intValue();
operandStack.push(new Integer(op2 - op1));
}
else if ((op == '*')) {
int op1 = ((Integer)(operandStack.pop())).intValue();
int op2 = ((Integer)(operandStack.pop())).intValue();
operandStack.push(new Integer(op2 * op1));
}
else if (op == '/') {
int op1 = ((Integer)(operandStack.pop())).intValue();
int op2 = ((Integer)(operandStack.pop())).intValue();
operandStack.push(new Integer(op2 / op1));
}
}
}
Converting Infix to Postfix
 Manual Transformation (Continued)
 Example: A + B * C
 Step 1: (A + ( B * C ) )
 Change all infix notations in each parenthesis to postfix notation
starting from the innermost expressions. This is done by moving
the operator to the location of the expression’s closing parenthesis
 Step 2: ( A + ( B C * ) )
 Step 3: ( A ( B C * ) + )
67
Converting Infix to Postfix
Manual Transformation (Continued)
 Example: A + B * C
 Step 2:
 Step 3:
(A + ( B * C ) )
(A ( B C * ) + )
 Remove all parentheses
 Step 4:
68
ABC*+
Converting Infix to Postfix
 Another Example
 (A + B ) * C + D + E * F - G
 Add Parentheses
( ( ( ( (A + B ) * C ) + D ) + ( E * F ) ) - G )
 Move Operators
( ( ( ( (A B + ) C * ) D + ) ( E F * ) + ) G - )
 Remove Parentheses
A B+ C * D+EF * +G -
69
Converting Infix to Postfix
Solution Version 2 - Parsing Strategy
 Example:
A*B
 Write to output A,
 Store the * on a stack,
 Write the B, then
 Get the * from the stack and write it to output.
 So, solution is: A B *
70
Converting Infix to Postfix
Precedence of operators
Highest
Lowest:
71
2:
* /
1:
+ -
0:
(
Converting Infix to Postfix
Conversion Algorithm
while there is more data
get the first symbol
if symbol = (
put it on the stack
if symbol = )
take item from top of stack
while this item != (
add it to the end
of the output string
Cont....
72
Converting Infix to Postfix
if symbol is +, -, *, \
look at top of the stack
while (stack is not empty AND the priority of the
current symbol is less than OR equal to the
priority of the symbol on top of the stack )
Get the stack item and add it to
the end of the output string;
put the current symbol on top of the stack
if symbol is a character
add it to the end of the output string
End loop
Cont....
73
Converting Infix to Postfix
Finally
While ( stack is not empty )
Get the next item from the stack and place it
at the end of the output string
End
74
Converting Infix to Postfix
Function precedence_test
case operator “*”
return 2;
case operator “+”
return 1;
case operator “(“
return 0;
default
return 99;
75
(operator)
OR “/”
OR “-”
//signals error condition!
Converting Infix to Postfix
The line we are analyzing is: A*B-(C+D)+E
Input Buffer
*B-(C+D)+E
B-(C+D)+E
-(C+D)+E
(C+D)+E
C+D)+E
+D)+E
D)+E
)+E
+E
E
76
Operator Stack
EMPTY
*
*
-(
-(
-(+
-(+
+
+
EMPTY
Output String
A
A
AB
AB*
AB*
AB*C
AB*C
AB*CD
AB*CD+
AB*CD+AB*CD+-E
AB*CD+-E+
Converting Infix to Postfix
1/4
public static void main(String[] args) {
// Provide a correct infix expression to be converted
String expression = "( 1 + 2 ) * 3";
try {
System.out.println(infixToPostfix(expression));
}
catch (Exception ex) {
System.out.println("Wrong expression");
}
}
public static String infixToPostfix(String expression) {
// Result string
String s = "";
// Create operatorStack to store operators
Stack operatorStack = new Stack();
// Extract operands and operators
StringTokenizer tokens = new StringTokenizer(expression, "()+-/*%", true);
77
Converting Infix to Postfix
2/4
// Phase 1: Scan tokens
while (tokens.hasMoreTokens()) {
String token = tokens.nextToken().trim(); // Extract a token
if (token.length() == 0) { // Blank space
continue; // Back to the while loop to extract the next token
}
else if (token.charAt(0) == '+' || token.charAt(0) == '-') {
// remove all +, -, *, / on top of the operator stack
while (!operatorStack.isEmpty() &&
(operatorStack.peek().equals('+') ||
operatorStack.peek().equals('-') ||
operatorStack.peek().equals('*') ||
operatorStack.peek().equals('/')
)) {
s += operatorStack.pop() + " ";
}
// push the incoming + or - operator into the operator stack
operatorStack.push(new Character(token.charAt(0)));
}
78
Converting Infix to Postfix
79
3/4
else if (token.charAt(0) == '*' || token.charAt(0) == '/') {
// remove all *, / on top of the operator stack
while (!operatorStack.isEmpty() &&
(operatorStack.peek().equals('*') ||
operatorStack.peek().equals('/')
)) {
s += operatorStack.pop() + " ";
}
// Push the incoming * or / operator into the operator stack
operatorStack.push(new Character(token.charAt(0)));
}
else if (token.trim().charAt(0) == '(') {
operatorStack.push(new Character('(')); // Push '(' to stack
}
else if (token.trim().charAt(0) == ')') {
// remove all the operators from the stack until seeing '('
while (!operatorStack.peek().equals('(')) {
s += operatorStack.pop() + " ";
}
operatorStack.pop(); // Pop the '(' symbol from the stack
}
else { // An operand scanned
// Push an operand to the stack
s += token + " ";
}
}
Converting Infix to Postfix
4/4
// Phase 2: remove the remaining operators from the stack
while (!operatorStack.isEmpty()) {
s += operatorStack.pop() + " ";
}
// Return the result
return s;
}
80