CC4 Reviewer
CC4 Reviewer
CC4 Reviewer
Stacks
➢ A list with the restriction that insertion and deletion can be performed only from one end, called the top.
Operations:
• Before this operation, the stack is often checked if it has enough capacity to accommodate the new item.
• If stack is full, an overflow would occur.
Pop() – removing the most recent item or element from the stack.
• Must ensure that the stack is not empty before this operation.
• If stack contains no item, popping would cause an underflow error.
Top() – returns the copy of the item or element at the top of the stack.
Create – generates an empty stack object and reserves necessary storage space.
Destroy – removes all elements from the stack and releases memory allocated to stack.
Algorithm of push()
The process of putting a new data element onto stack is known as a Push Operation. Push operation involves a series of
steps:
Algorithm of pop()
Accessing the content while removing it from the stack, is known as a Pop Operation. In an array implementation of pop()
operation, the data element is not actually removed, instead top is decremented to a lower position in the stack to point to
the next value. But in linked-list implementation, pop() actually removes data element and deallocates memory space.
Array Implementation
Linked-List Implementation
• Elements are inserted and removed only from the head of the list.
• A header node is not used because no special-case code is required for lists of zero or one elements.
• The only data member is top, a pointer to the first (top) link node of the stack.
• Method push first modifies the next field of the newly created link node to point to the top of the stack and then
sets top to point to the new link node.
• Method pop is also quite simple. Variable temp stores the top nodes’ value, while ltemp links to the top node as it
is removed from the stack.
• The stack is updated by setting top to point to the next link in the stack.
• The old top node is then returned to free store (or the freelist), and the element value is returned.
Push
Pop
removeFront(): returns and removes the element at the front of the list
removeBack(): returns and removes the element at the end of the list
Stack Applications
Recursion Implementation
• Perhaps the most common computer application that uses stacks is not even visible to its users. This is the
implementation of subroutine calls in most programming language runtime environments.
• A subroutine call is normally implemented by placing necessary information about the subroutine (including the
return address, parameters, and local variables) onto a stack.
• This information is called an activation record. Further subroutine calls add to the stack. Each return from a
subroutine pops the top activation record off the stack.
Implementing recursion with a stack. β values indicate the address of the program instruction to return to after completing
the current function call. On each recursive function call to fact, both the return address and the current value of n must be
saved. Each return from fact pops the top activation record off the stack.
• Parentheses are used in arithmetic expressions to specify priority of evaluation in a valid expression, ‘(‘ match
with a corresponding ‘)’
• The following expression has the same number of ‘)’ and ‘(‘ , but it is illegal.
A+)+(C+D)+(
We can use a stack to validate an expression
using the following algorithm:
• Array scheme is suitable for stacks with fixed number of data items. Its implementation is simple.
• By contrast, the linked list implementation is complex but flexible.
Advantages of Stacks
• Helps manage the data in particular way (LIFO) which is not possible with Linked list and array.
• When function is called the local variables are stored in stack and destroyed once returned. Stack is used when
variable is not used outside the function.
• It gives control over how memory is allocated and deallocated.
• Stack frees you from the burden of remembering to cleanup(read delete) the object.
• Not easily corrupted (No one can easily inset data in middle).
Disadvantages of Stacks
Algebraic Expression
• POSTFIX: Postfix notation are also known as Reverse Polish Notation (RPN). They are different from the infix and
prefix notations in the sense that in the postfix notation, operator comes after the operands, e.g. xy+, xyz+* etc.
• PREFIX: Prefix notation also known as Polish notation. In the prefix notation, operator comes before the operands,
e.g. +xy, *+xyz etc.
Tie Breaker
➢ When an operand lies between two operators that have the same priority, the operand associates with the
operator on the left.
a+b–c
a*b/c/d
Delimeters
Sub expression within delimiters is treated as a single operand, independent from the remainder of the expression.
(a + b) * (c – d) / (e – f)
Why?
• Why use PREFIX and POSTFIX notations when we have simple INFIX notation?
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 Associative property
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.
3. Postfix and prefix expression forms do not rely on operator priorities, a tie breaker, or delimiters.
4. 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 Associative property (order of brackets).
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.
3. Expressions are evaluated from left to right. Precedence rules and parentheses are never needed!!
Postfix Examples
4. If it is an operator, then
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 stack and output them until an opening parenthesis is encountered.
pop and discard the opening parenthesis.
1. Each operator in a postfix string refers to the previous two operands in the string.
2. Suppose that each time we read an operand we push it into a stack. When we reach an operator, its operands will then
be top two elements on the stack
3. We can then pop these two elements, perform the indicated operation on them, and push the result on the stack.
4. When an operator is encountered, the indicated action is performed using the top elements of the stack, and the result
replaces the operands on the stack.
Evaluating a postfix expression
Algorithm:
Initialize result as a blank string, Iterate through given expression, one character at a time
i. If the operator’s precedence is greater than or equal to the precedence of the stack top of the operator stack, then
push the character to the operator stack.
ii. If the operator’s precedence is less than the precedence of the stack top of operator stack then “pop out an operator
from the stack and add it to the result until the stack is empty or operator’s precedence is greater than or equal to
the precedence of the stack top of operator stack“. then push the operator to stack.
Queues
• is a list-like structure that provides restricted access to its elements. Queue elements may only be inserted at the
back (called an enqueue operation) and removed from the front (called a dequeue operation). Queues operate like
standing in line at a movie theater ticket counter. They call a queue a “FIFO” list, which stands for “First-In, First-
Out.”
• Feature/ Operations
• No Implementation details
In real world, a queue is a structure goes in first, comes out first or called FIFO.
A stack is a collection in which both insertion and removal happen on the same end that we called pop out stack.
In Queue, however an insertion must happen at one end that we call rear or tail of the queue and any removal must happen
at the other end called front or end of the queue
• a List or collection with the restriction that insertion can be performed at one end (rear) and deletion can be
performed at the other end (front).
Operations
• EnQueue(x)
• DeQueue()
• Front()
• IsEmpty
• Logically a Queue can be shown as a figure or container, open from two sides, so an element can be inserted or
enqueued from one side and can be remove or dequeued on the other side.
• A Printer shared on a network. Any machine on the network can send print request on the printer but it can only
print one request at a time. When a request comes and the printer is busy, the printer will not say that can’t you see
I’m busy, what really happens is the program will put the request in a queue.
Queue Implementation
The linked queue implementation is a straightforward adaptation of the linked list. Methods front and rear are pointers to
the front and rear queue elements, respectively. We will use a header link node, which allows for a simpler implementation
of the enqueue operation by avoiding any special cases when the queue is empty. On initialization, the front and rear
pointers will point to the header node, and front will always point to the header node while rear points to the true last link
node in the queue. Method enqueue places the new element in a link node at the end of the linked list (i.e., the node that
rear points to) and then advances rear to point to the new link node. Method dequeue removes and returns the first element
of the list.
SORTING
SEARCHING
• Given a list of data find the location of a particular value or report that value is not present
• linear search
✓ intuitive approach
✓ start at first item
✓ is it the one I am looking for?
✓ if not go to next item
✓ repeat until found or all items checked
✓ If items not sorted or unsortable this approach is necessary
Linear Search
Sorting
Sorting Categories
1. Internal Sorting – The data collection to be sorted is kept in the main memory.
2. External Sorting – The sorting of data stored on secondary devices. Data is sorted in the main memory and written back
to the secondary device.
In this method, the storage device used is only In this method, the storage devices are both
Main memory (RAM). Secondary memory (Hard disk) and Main Memory
(RAM).
Examples: Example:
Bubble sort, Insertion sort, Quick sort, Heap sort External Merge Sort.
etc.
Bubble Sort
• Bubble sort is the simplest iterative algorithm operates by comparing each item or element with the item next to it and
swapping them if needed. In simple words, it compares the first and second element of the list and swaps it unless they
are out of specific order. Similarly, Second and third element are compared and swapped, and this comparing and
swapping go on to the end of the list.
• The number of comparisons in the first iteration are n-1 where n is the number elements in an array. The largest element
would be at nth position after the first iteration. And after each iteration, the number of comparisons decreases and at last
iteration only one comparison takes place.
Advantages Disadvantage/s
It is easy to understand Sorting takes a long time
Easy to implement
No demand for large amounts of memory
Once sorted, data is available for processing
The best-case scenario is depicted by O(n). In this instance, the algorithm executes in a time directly proportional to the
size of the array. The worst-case scenario of its operation occurs when the array needs to be 'reverse sorted' and is
depicted by O (n^2) where the time increases exponentially as the number of sorted elements increase
The Bubble sort is the simplest sorting algorithm. But it is also the slowest of all. Let’s have a look about its efficiency.
Let’s have an array of size 10 to be sorted.
In the first pass of the loop it makes 9 comparisons, and with the second pass it makes 8 comparisons, and so on, down
to one comparison on the last pass. So, for 10 items, it makes:
9+8+7+6+5+4+3+2+1 = 45
Selection Sort
Selection sort has achieved slightly better performance and is efficient than bubble sort algorithm. Suppose we want to
arrange an array in ascending order then it functions by finding the largest element and exchanging it with the last
element and repeat the following process on the sub-arrays till the whole list is sorted.
In selection sort, the sorted and unsorted array does not make any difference and consumes an order of n2 (O(n2)) in
both best- and worst-case complexity. Selection sort is faster than Bubble sort.
Advantages Disadvantages
The main advantage of the selection sort is that it The primary disadvantages of the selection sort is
performs well on a small list. its pore efficiency when dealing with a huge list of
items.
Because it is an in-place sorting algorithm, no The selection sort requires n-squared number of
additional temporary storage is required beyond steps for sorting n elements.
what is needed to hold the original list.
Its performance is easily influenced by the initial Quick Sort is much more efficient than selection
ordering of the items before the sorting process. sort
Selection sort loops over indices in the array; for each index, selection sort calls indexOfMinimum and swap. If the length
of the array is nnn, there are nnn indices in the array.
Since each execution of the body of the loop runs two lines of code, you might think that 2 n2n2, n lines of code are executed
by selection sort. But it is not true!
Remember that indexOfMinimum and swap are functions: when either is called, some lines of code are executed.
findMinimumFromUnSortedPart(int[] intArray, int startIndexOfUnSorted) – It finds the smallest element in a given array
from the starting index of the unsorted part. The max operation is N – 1. This step scans all elements. If the elements
change, then have to redo. In this case, Insertion sort is a better choice.
sortAsc(int[] intArray) – It iterates the array and swaps the left-most element in the unsorted part to the smallest element
found for each iteration.
It is like bubble sort but works the other way around. It selects the smallest element from the entire array and moves to the
first position. Then it moves onto finding the smallest among 1 to n and so on till we reach all n positions. Basically, it
selects the element at each position from 0 to n. The worst-case runtime is O(n2) for selection sort as well.
1. In the bubble sort, each element and its adjacent element is compared and swapped if required. On the other hand,
selection sort works by selecting the element and swapping that element with the last element. The selected element
could be largest or smallest depending on the order i.e., ascending or descending.
2. The worst-case complexity is same in both the algorithms, i.e., O(n2), but best complexity is different. Bubble sort takes
an order of n time whereas selection sort consumes an order of n2 time.
4. Selection sort algorithm is fast and efficient as compared to bubble sort which is very slow and inefficient.
Conclusion
Bubble sort algorithm is the most simple and inefficient algorithm, but selection sort algorithm is efficient as compared to
bubble sort. Bubble sort also consumes additional space for storing temporary variable and needs more swaps.
Insertion sort is a simple sorting algorithm that allows for efficient, in-place sorting of the array, one element at a time. By
in-place sorting, we mean that the original array is modified, and no temporary structures are needed. The array is virtually
split into a sorted and an unsorted part. Values from the unsorted part are picked and placed at the correct position in the
sorted part.
Algorithm
To sort an array of size n in ascending order:
1. Iterate from arr[1] to arr[n] over the array.
2. Compare the current element (key) to its predecessor.
3. If the key element is smaller than its predecessor, compare it to the elements before. Move the greater elements one
position up to make space for the swapped element.
The iteration starts at the index = 1, and checks all values on the left side of the key
As it checks values only on the left side, the new key is now index = 2
As the values on the left side of 12 are all smaller, the new key is index = 3
As all values are less than 12 on its left side, the new key is at index = 4. Same values are not swapped
Advantages Disadvantages
The main advantage of the insertion sort is its The disadvantage of the insertion sort is that is
simplicity does not perform as well as other, better sorting
algorithm.
It also exhibits a good performance when dealing With n – squared steps required for every n
with a small list. element to be sorted, the insertion sort does bot
deal well with a huge list.
The insertion sort is an in-place sorting algorithm, The insertion sort is particularly useful only when
so the space requirement is minimal. sorting a list of few items.
1. The first step is to create a method that takes in input the array to be sorted, sort arr as seen in line 3 in the code above.
2. The second step is to create an outer for loop which will iterate over each element of the array as shown in line 5.
3. The third step is to create a separate iterator, j which will check for the ascending order of elements in the list, as shown
in line 7.
• As shown in line 9 the while loop must satisfy two conditions: the value of j must be greater than 0, and the value
at index j-1, must be greater than the value at index j.
• If this condition holds true then, as shown from lines 11 to 14, the key is set to the value at index j.
• Then the values at j and j-1 are swapped.
• The value of j is reduced by 1 and the loop continues till one of the conditions breaks.
5. This continues for every iteration of the outer for loop till that also breaks.
Merge Sort
1. A merge sort is a type of a divide and conquer algorithm used to sort a given array; this means that the array is divided
into halves and then further sub-divided till division can no longer take place.
2. This happens when you reach a single element array as that has no middle to further divide the array on. Each divided
sub-array is then sorted and subsequently merged with other sub-divisions. The sorted merge continues till all divisions of
the array have been merged, giving us a sorted array.
3. The merge() function is used for merging two halves. The merge(arr, l, m, r) is key process that assumes that arr[l..m]
and arr[m+1..r] are sorted and merges the two sorted sub-arrays into one. See following C implementation for details.
• Given an array, we need to sort it using Merge Sort. Hence, we must divide the array into half
• Divide the subarrays further
• Divide all subarrays further, except the one on the far right
• Now that all subarrays are of length 1, they can be sorted and merged
• This shows the first sorting step, if an element has a larger value on the left, it is swapped with its partner on the
right
• The subarrays are now merged with one another. When merging the left subarrays, 12 and 10 swap positions as
while merging, sorting takes place again
• The final sorted merge takes place. Giving us, the sorted array
Advantages Disadvantages
It can be applied to files of any size. Requires extra space >>N
Reading of the input during the run-creation step is Merge Sort requires more space than other sort
sequential ➔Not much seeking.
If heap sort is used for the in-memory part of the Merge sort is less efficient than another sort
merge, its operation can be overlapped with l/0
Implementation of Insertion Sort
The implementation of Merge Sort given above is a recursive one. You start by calling the mergeSort method as shown on
line 51 with the following input parameters: