Data Structures
Data Structures
Data structures
• A data structure is a systematic way of organizing a collection of data.
• A static data structure is one whose capacity is fixed at creation.
• A dynamic data structure is one whose capacity is variable, e.g.: a linked list, or
binary tree.
• For each data structure, we need algorithms for insertion, deletion, searching, etc.
• Algorithms:
✓ can be performed by humans or machines
✓ can be expressed in any suitable language
✓ may be as abstract as we like.
• Programs:
✓ must be performed by machines
✓ must be expressed in a programming language
✓ must be detailed and specific.
Array
• An array is a collection of items stored at contiguous memory locations.
• The idea is to store multiple items of the same type together.
• This makes it easier to calculate the position of each element by simply adding an
offset to a base value, i.e., the memory location of the first element of the array
(generally denoted by the name of the array).
• Why Do You Need an Array in Data Structures?
✓ Let's suppose a class consists of ten students, and the class must publish their results.
✓ If you had declared all ten variables individually, it would be challenging to manipulate
and maintain the data.
✓ If more students were to join, it would become more difficult to declare all the variables
and keep track of it.
▪ To overcome this problem, arrays came into the picture.
Ordered Array
• The elements of an ordered array are arranged in ascending (or descending) order.
Stacks
• A container of objects that are inserted and removed according to the last-in-first-
out (LIFO) principle.
• Only the last (the most recently inserted) object can be removed.
Stack Operations
• Some stack operations:
✓ push - add an item to the top of the stack
✓ pop - remove an item from the top of the stack
✓ peek - retrieves the top item without removing it
✓ empty - returns true if the stack is empty
Queue
• Differs from a stack in that its insertion and removal follow the first-in-first-out
(FIFO) principle.
• The element which has been in the queue the longest may be removed.
Queue Operations
• We can define the operations for a queue
• enqueue - add an item to the rear of the queue
• dequeue (or serve) - remove an item from the front of the queue
• empty - returns true if the queue is empty
linked list
• A linked list is a linear data structure, in which the elements are not stored at
contiguous memory locations.
• Linked List contains a link element called first.
• Each link carries a data field(s) and a link field called next.
• Each link is linked with its next link using its next link.
• The last link carries a link as null to mark the end of the list.
Basic Operations
• Insertion − Adds an element at the beginning of the list.
• Deletion − Deletes an element at the beginning of the list.
• Display − Displays the complete list.
• Search − Searches an element using the given key.
• Delete − Deletes an element using the given key.
Tree
• A collection of objects arranged hierarchically.
• E.g., organization of a corporation, a table of content, dos/Unix file systems, and
family tree.
• The notion of parents and children, root, and leaves.
Binary Trees
• Why Use Binary Trees?
✓ You can search a tree quickly, as you can with an ordered array,
✓ you can also insert & delete items quickly, with a linked list.
✓Arrays represent multiple data items of the same type using a single name.
✓Elements can be accessed randomly by using the index number.
✓Easy access to all the elements.
✓Traversal through the array becomes easy using a single loop.
✓Sorting becomes easy as it can be accomplished by writing fewer lines of code.
✓An array is a static structure, which allows a fixed number of elements to be entered that is
decided at the time of declaration.
✓Allocating more memory than the requirement leads to a waste of memory space and less
memory allocation also leads to a problem.
Unsorted array
Search in an unsorted array (Sequential Search)
• In an unsorted array, a search operation can be performed by linear traversal from
the first element to the last element. The time complexity of search in an unsorted
array is 𝑶(𝒏)
Example
• Original list:
✓ 10, 30, 20, 80, 70, 10, 60, 40, 70
• Sorted in non-decreasing order:
✓ 10, 10, 20, 30, 40, 60, 70, 70, 80
• Sorted in non-increasing order:
✓ 80, 70, 70, 60, 40, 30, 20, 10, 10
Issues in Sorting
• Many issues are there in sorting techniques
✓ How to rearrange a given set of data?
✓ Which data structures are more suitable to store data before their sorting?
✓ How fast the sorting can be achieved?
✓ How sorting can be done in a memory constraint situation?
✓ How to sort various types of data?
Sorting by Comparison
• The basic operation involved in this type of sorting technique is comparison. A data
item is compared with other items in the list of items to find its place in the sorted
list.
✓ Insertion:
▪ From a given list of items, one item is considered at a time. The item chosen is
then inserted into an appropriate position relative to the previously sorted
items. The item can be inserted into the same list or a different list.
❖ e.g.: Insertion sort
✓ Selection:
▪ First, the smallest (or largest) item is located, and it is separated from the
rest; then the next smallest (or next largest) is selected, and so on until all
items are separated.
❖ e.g.: Selection sort, Heap sort
✓ Exchange:
▪ If two items are found to be out of order, they are interchanged. The process is
repeated until no more exchange is required.
❖ e.g.: Bubble sort, Shell Sort, Quick Sort
✓ Enumeration:
▪ Two or more input lists are merged into an output list and while merging the
items, an input list is chosen following the required sorting order.
❖ e.g.: Merge sort
Sorting by Distribution
• No key comparison takes place
• All items under sorting are distributed over an auxiliary storage space based on the
constituent elements in each and then grouped to get the sorted list.
• Distributions of items based on the following choices
✓ Radix - An item is placed in a space decided by the bases (or radix) of its
components with which it is composed.
✓ Counting - Items are sorted based on their relative counts.
✓ Hashing - Items are hashed, that is, dispersed into a list based on a hash function.
• Note: This lecture concentrates only on sorting by comparison.
Insertion Sort
• In insertion sort, each successive element in the array to be sorted is inserted into
its proper place with respect to the other, already sorted elements.
✓ We divide our array into a sorted and an unsorted array
✓ Initially, the sorted portion contains only one element: the first element in the array.
✓ We take the second element in the array and put it into its correct place
• Example:
✓ 99 | 55 4 66 28 31 36 52 38 72
✓ 55 99 | 4 66 28 31 36 52 38 72
✓ 4 55 99 | 66 28 31 36 52 38 72
✓ 4 55 66 99 | 28 31 36 52 38 72 Click on the word link to
✓ 4 28 55 66 99 | 31 36 52 38 72 see the code
✓ 4 28 31 55 66 99 | 36 52 38 72
✓ 4 28 31 36 55 66 99 | 52 38 72
✓ 4 28 31 36 52 55 66 99 | 38 72
✓ 4 28 31 36 38 52 55 66 99 | 72
✓ 4 28 31 36 38 52 55 66 72 99 |
Selection Sort
• Selection sort is a sorting algorithm that works as follows:
✓ Find the minimum value in the list
✓ Swap it with the value in the first position
✓ Repeat the steps above for the remainder of the list (starting at the second
position).
• Example:
✓ 26 33 43 100 46 88 52 17 53 77
✓ 17 | 33 43 100 46 88 52 26 53 77
✓ 17 26 | 43 100 46 88 52 33 53 77
✓ 17 26 33 | 100 46 88 52 43 53 77
✓ 17 26 33 43 | 46 88 52 100 53 77 Click on the word link to
✓ 17 26 33 43 46 | 88 52 100 53 77 see the code
✓ 17 26 33 43 46 52 | 88 100 53 77
✓ 17 26 33 43 46 52 53 | 100 88 77
✓ 17 26 33 43 46 52 53 77 | 88 100
✓ 17 26 33 43 46 52 53 77 88 | 100
Bubble Sort
• The sorting process proceeds in several passes.
✓ In every pass, we go on to compare neighboring pairs and swap them if out of
order.
✓ In every pass, the largest of the elements under consideration will bubble to the
top (i.e., the right).
• How do you make the best case with (n-1) comparisons only?
✓ By maintaining a variable flag, check if there have been any swaps in each pass.
✓ If not, the array is already sorted.
Quicksort Algorithm
• Given an array of n elements (e.g., integers):
✓ If the array only contains one element, return
✓ Else
▪ pick one element to use as a pivot.
▪ Partition elements into two sub-arrays:
❖ Elements less than or equal to the pivot
❖ Elements greater than the pivot
▪ Quicksort two sub-arrays
▪ Return results
Partitioning Array
• Given a pivot, partition the elements of the array such that the resulting array
consists of:
✓ One sub-array that contains elements >= pivot
✓ Another sub-array that contains elements < pivot
• The sub-arrays are stored in the original data array.
• Partitioning loops through, swapping elements below/above the pivot.
While While If too_big_index <
data[too_big_index] <= data[too_small_index] too_small_index While too_small_index
data[pivot] > data[pivot] swap data[too_big_index] > too_big_index, go to
++too_big_index --too_small_index and data[too_small_index] 1.
Swap
data[too_small_index]
and data[pivot_index] Click on the word link to
see the code
Merge Sort
How does it work?
Stack Implementation
• To implement a stack, we need to define a class named Stack and use an array for
storing their elements and define a function for each main operation.
Default Constructor
• When the stack object declared
✓ Initializes stack to an empty state
✓ Sets stackTop to NULL
Initialize Stack
• Reinitializes stack to an empty state
• Because the stack might contain elements and you are using a linked
implementation of a stack
✓ Must deallocate memory occupied by the stack elements, set stackTop to NULL
Push
• newElement added at the beginning of the linked list pointed to by stackTop
• Value of pointer stackTop updated
Return the Top Element
• Returns information of the node to which stackTop pointing
Pop
• Removes the top element of the stack
✓ Node pointed to by stackTop removed
✓ Value of pointer stackTop update
Copy Stack
✓ Makes an identical copy of a stack
INSERT A NODE
• Case 1: Insertion in an empty list
• Case 2: Insertion at the beginning of a nonempty list
• Case 3: Insertion at the end of a nonempty list
• Case 4: Insertion somewhere in a nonempty list
• Both cases 1 and 2 require us to change the value of the pointer first.
• Cases 3 and 4 are similar. After inserting an item, the count is incremented by 1.
DELETE A NODE
• We first search the list to see whether the item to be deleted is in the list.
• This operation (if the item to be deleted is in the list) requires the adjustment of two
pointers in certain nodes.
• Case 1: The list is empty.
• Case 2: The item to be deleted is in the first node of the list, which would require us
to change the value of the pointer first.
• Case 3: The item to be deleted is somewhere in the list.
• Case 4: The item to be deleted is not on the list
Overflow vs underflow
• If a program attempts to add an entry to a queue that is already at its capacity, this
is, of course, an error.
• This error is called queue overflow.
• If a program attempts to remove an entry from an empty queue, that is another kind
of error, called queue underflow.
Array Implementation
• A queue can be implemented with an array, as shown here. For example, this
queue contains the integers 4 (at the front), 8, and 6 (at the rear).
• The easiest implementation also keeps track of the number of items in the queue
and the index of the first element (at the front of the queue), and the last element
(at the rear).
A Dequeue Operation
• When an element leaves the queue, size is decremented, and first changes, too.
An Enqueue Operation
• When an element enters the queue, size is incremented, and the last changes, too.
Array Implementation
• Easy to implement
• But it has a limited capacity with a fixed array
• Special behavior is needed when the rear reaches the end of the array.
Recognizing Palindromes
• A palindrome is a string that reads the same forward and backward; that is, the
letters are the same whether you read them from right to left or from left to right.
• For example, the one-word string “radar” is a palindrome.
• Able was I ere I saw Elba
• We can do this by using both a stack and a queue.
• We will read the line of text into both a stack and a queue
• The program can simply compare the contents of the stack and the queue
character-by-character to see if they would produce the same string of characters.
Summary
• Like stacks, queues have many applications.
• Items enter a queue at the rear and leave a queue at the front.
• Queues can be implemented using an array or using a linked list.
Subtree
• Any node in a tree also can be viewed as the root of a new, smaller tree.
Depth of a node.
• Suppose you start at a node n and move upward to its parent.
• We’ll call this “one step.” Then move up to the parent of the parent—that’s a second
step.
• Eventually, you will reach the root, and the number of steps taken is called the depth
of the node n.
Depth of a tree/ height of a tree
• The depth of a tree is the maximum depth of any of its leaves
• the leaf containing 13 has a depth of three, and there is no deeper leaf.
• If a tree has only one node, the root, then its depth is zero (since the depth of the
root is zero).
• The empty tree doesn’t have any leaves, so we use –1 for its depth.
• If a tree has only one node, the root, then its depth is zero (since the depth of the
root is zero).
• The empty tree doesn’t have any leaves, so we use –1 for its depth.
Full binary trees
• In a full binary tree, every leaf has the same depth,
• and every non-leaf has two children.
Complete binary trees
• To be a complete tree, every level except the deepest must contain as many nodes as
possible; and at the deepest level, all the nodes are as far left as possible.
• In a complete binary tree, all the depths are full, except perhaps for the deepest. At
the deepest depth, the nodes are as far left as possible.
• A complete binary tree is a special kind of binary tree that will be useful to us.
Tree class
• Such a class will have at least two private member variables:
✓ The array itself is one member variable, and
✓ A second member variable keeps track of how much of the array is used.
• The actual links between the nodes are not stored.
Tree links
• Instead, these links exist only via the formulas that determine where an item is
stored in the array based on the item’s position in the tree.
Summary
• Binary trees contain nodes.
• Each node may have a left child and a right child.
• If you start from any node and move upward, you will eventually reach the root.
• Every node except the root has one parent. The root has no parent.
• Complete binary trees require the nodes to fill in each level from left to right before
starting the next level.