The last element pushed onto the stack is the first element to be popped off the stack
Only the element on the top of the stack can be accessed
Stack Methods
Push
Add an element to the top of the stack
Pop
Remove the top element of the stack
Stack Implementation
Implement a Stack class by wrapping a linked list
Stacl uses the linked list and adapts its methods to implement push and pop
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classStack[A] {
var top: LinkedListNode[A] = null
defpush(a: A): Unit = { this.top = newLinkedListNode[A](a, this.top) }
defpop(): A = { val toReturn = this.top.value this.top = this.top.next toReturn } }
Stack Usage
Create a new empty Stack
Call push to add an element to the top
Call pop to remove an element
Same exact usage when using Scala’s builtin Stack
1 2 3 4 5 6 7
val stack = newStack[Int]() stack.push(3) stack.push(7) stack.push(2) stack.push(-5)
val element = stack.pop()
We can use Scala’ss list as a Stack
The preferred way to use the concept of a stack in practice
1 2
@deprecated("Stack is an inelegant and potentially poorly-performing wrapper around List. Use List instead: stack push x becomes x :: list; stack.pop is list.tail.", "2.11.0") classStack[+A] protected (protected val elems: List[A])
This is very efficient!
But wait..doesn’t this create a new list each time an element is pushed or popped since List is immutable?
Find the first operator and evaluate it using the previous 2 operands
Repeat until there are no operators
Infix -> Postfix
Shunting Yard
Convert infix to postfix
Read expression left to right
Copy operands to the output
Push operatos and parentheses onto a stack
If reading “)”, move top of stack to output until “(“ is popped
If readingg an operator, first move top of stack to output until a lower precedent (Should be evaluated later) operator is on top or the stack is empty
After reading the entire input, copy the rest of the stack to the output
1
(12-4) - (8+9/3*2) -> 124 - 893 / 2 * + -
Lecture Question
Task: Implement a backlog to track tasks that can’t be completed immediately
In a package named datastructures, write a class named Backlog with the following functionality
Takes a type parameter A
Takes a function in its constructor of type A => Unit
Has a method named addTask that takes a task of type A and returns Unit that adds the task to the backlog (A queue)
Has a method named completeTask that takes no parameters and returns Unit that calls the function (from the constructor) on the oldest task in the backlog and removes that task from the backlog
If the Backlog is empty, this method does nothing
Testing: In a package named “tests” create a class named “TestBacklog” as a test suite that tests the functionality above