Data Structures
Introduction
Stacks
Queues
Linked Lists
Sorting
Searching
Introduction
Linked lists
Allow insertions and removals anywhere
Stacks
Allow insertions and removals only at top of stack
Queues
Allow insertions at the back and removals from the front
Stacks
Stack
New nodes can be added and removed only at the top
Similar to a pile of dishes
Last-in, first-out (LIFO)
Bottom of stack indicated by a link member to NULL
Constrained version of a linked list
push
Adds a new node to the top of the stack
pop
Removes a node from the top
Stores the popped value
Returns true if pop was successful
Last In First Out
B
top A
C
top B
A
D
top C
B
A
top
E
D
C
B
A
top
D
C
B
A
Stack Operation:
CreateS, isEmpty, isFull
Stack createS(max_stack_size) ::=
#define MAX_STACK_SIZE 100 /* maximum stack size */
typedef struct {
int key;
/* other fields */
} element;
element stack[MAX_STACK_SIZE];
int top = -1;
Boolean isEmpty(Stack) ::= top< 0;
Boolean isFull(Stack) ::= top >= MAX_STACK_SIZE-1;
Push
void push(int *top, element item)
{
/* add an item to the global stack */
if (*top >= MAX_STACK_SIZE-1) {
stack_full( );
return;
}
stack[++*top] = item;
}
Pop
element pop(int *top)
{
/* return the top element from the stack */
if (*top == -1)
return stack_empty( ); /* returns and error key */
return stack[(*top)--];
}
Queues
Queue
Similar to a supermarket checkout line
First-in, first-out (FIFO)
Nodes are removed only from the head
Nodes are inserted only at the tail
Insert and remove operations
Enqueue (insert) and dequeue (remove)
First In First Out
rear
front
B
A
C
rear B
front A
D
rear C
B
front A
rear
D
C
front B
rear
front
Applications: Job Scheduling
front rear Q[0] Q[1] Q[2] Q[3]
-1
-1
-1
0 J1
-1
1 J1
J2
-1
2 J1
J2 J3
0
2
J2 J3
1
2
J3
Comments
queue is empty
Job 1 is added
Job 2 is added
Job 3 is added
Job 1 is deleted
Job 2 is deleted
Opearation:
createQ, isEmptyQ, isFullQ
Queue createQ(max_queue_size) ::=
# define MAX_QUEUE_SIZE 100/* Maximum queue size */
typedef struct {
int key;
/* other fields */
} element;
element queue[MAX_QUEUE_SIZE];
int rear = -1;
int front = -1;
Boolean isEmpty(queue) ::= front == rear
Boolean isFullQ(queue) ::= rear == MAX_QUEUE_SIZE-1
Enqueue (Input) :
void enqueue(int *rear, element item)
{
/* add an item to the queue */
if (*rear == MAX_QUEUE_SIZE_1) {
queue_full( );
return;
}
queue [++*rear] = item;
}
Dequeue (Output):
element dequeue(int *front, int rear)
{
/* remove element at the front of the queue */
if ( *front == rear)
return queue_empty( ); /* return an error key
*/
return queue [++ *front];
}
Linked Lists
Linked list
Linear collection of self-referential class objects,
called nodes
Connected by pointer links
Accessed via a pointer to the first node of the list
Subsequent nodes are accessed via the link-pointer
member of the current node
Link pointer in the last node is set to null to mark the
lists end
Use a linked list instead of an array when
You have an unpredictable number of data elements
Your list needs to be sorted quickly
Linked Lists
Types of linked lists:
Singly linked list
Begins with a pointer to the first node
Terminates with a null pointer
Only traversed in one direction
Circular, singly linked
Pointer in the last node points back to the first node
Doubly linked list
Two start pointers first element and last element
Each node has a forward pointer and a backward pointer
Allows traversals both forwards and backwards
Circular, doubly linked list
Forward pointer of the last node points to the first node and backward
pointer of the first node points to the last node
Linked lists
Before further discussion of linked lists, we need to explain
the notation we use in the figures. We show the connection
between two nodes using a line. One end of the line has an
arrowhead, the other end has a solid circle.
The concept of copying and storing pointers
Operations on linked lists
The same operations we defined for an array can be applied
to a linked list.
Searching a linked list
Since nodes in a linked list have no names, we use two
pointers, pre (for previous) and cur (for current). At the
beginning of the search, the pre pointer is null and the cur
pointer points to the first node. The search algorithm moves
the two pointers together towards the end of the list. Figure
11.13 shows the movement of these two pointers through the
list in an extreme case scenario: when the target value is
larger than any value in the list.
Moving of pre and cur pointers in searching a linked list
Values of pre and cur pointers in different cases
Inserting a node
Before insertion into a linked list, we first apply the
searching algorithm. If the flag returned from the searching
algorithm is false, we will allow insertion, otherwise we
abort the insertion algorithm, because we do not allow data
with duplicate values. Four cases can arise:
Inserting into an empty list.
Insertion at the beginning of the list.
Insertion at the end of the list.
Insertion in the middle of the list.
Inserting a node at the beginning of a linked list
Inserting a node at the end of the linked list
Inserting a node in the middle of the linked list
Deleting a node
Before deleting a node in a linked list, we apply the search
algorithm. If the flag returned from the search algorithm is
true (the node is found), we can delete the node from the
linked list. However, deletion is simpler than insertion: we
have only two casesdeleting the first node and deleting
any other node. In other words, the deletion of the last and
the middle nodes can be done by the same process.
Deleting the first node of a linked list
Deleting a node at the middle or end of a linked list
SEARCHING TECHNIQUES
1-LINEAR (SEQUENTIAL) SEARCH
2-BINARY SEARCH
SEARCHING TECHNIQUES
To finding out whether a particular element is
present in the list.
2 methods: linear search, binary search
The method we use depends on how the elements
of the list are organized
unordered list:
linear search: simple, slow
an ordered list
binary search or linear search: complex, faster
1. LINEAR (SEQUENTIAL) SEARCH
How?
Proceeds by sequentially comparing the key with
elements in the list
Continues until either we find a match or the end of
the list is encountered.
If we find a match, the search terminates
successfully by returning the index of the element
If the end of the list is encountered without a match,
the search terminates unsuccessfully.
1. LINEAR (SEQUENTIAL) SEARCH
void lsearch(int list[],int n,int element)
{ int i, flag = 0;
for(i=0;i<n;i++)
if( list[i] == element)
{ cout<<found at position<<i;
flag =1;
break; }
if( flag == 0)
cout<< not found;
}
flag: what for???
1. LINEAR (SEQUENTIAL) SEARCH
int lsearch(int list[],int n,int element)
{ int i, find= -1;
for(i=0;i<n;i++)
Another way using flag
if( list[i] == element)
{find =i;
break;}
return find;
average time: O(n)
}
2.
BINARY SEARCH
List must
be a sorted one
We compare the element with the element placed
approximately in the middle of the list
If a match is found, the search terminates
successfully.
Otherwise, we continue the search for the key in a
similar manner either in the upper half or the
lower half.
Baba?
Eat?
void bsearch(int list[],int n,int element)
{
int l,u,m, flag = 0;
l = 0; u = n-1;
while(l <= u)
{ m = (l+u)/2;
if( list[m] == element)
{cout<<"found:"<<m;
flag =1;
break;}
else
if(list[m] < element)
l = m+1;
else
u = m-1;
}
average time: O(log2n)
if( flag == 0)
cout<<"not found";
}
Sorting: Definition
Sorting: an operation that segregates items into
groups according to specified criterion.
A={3162134590}
A={0112334569}
Types of Sorting Algorithms
There are many, many different types of
sorting algorithms, but the primary ones
are:
Bubble Sort
Selection Sort
Merge Sort
Bubble Sort: Idea
Idea: bubble in water.
Bubble in water moves upward. Why?
How?
When a bubble moves upward, the water from above
will move downward to fill in the space left by the
bubble.
Bubble Sort Example
9, 6, 2, 12, 11, 9, 3, 7
6, 9, 2, 12, 11, 9, 3, 7
6, 2, 9, 12, 11, 9, 3, 7
6, 2, 9, 12, 11, 9, 3, 7
6, 2, 9, 11, 12, 9, 3, 7
6, 2, 9, 11, 9, 12, 3, 7
6, 2, 9, 11, 9, 3, 12, 7
6, 2, 9, 11, 9, 3, 7, 12
Bubblesort compares the numbers in pairs from left to right
exchanging when necessary. Here the first number is compared
to the second and as it is larger they are exchanged.
Now the next pair of numbers are compared. Again the 9 is the
larger and so this pair is also exchanged.
In the third comparison, the 9 is not larger than the 12 so no
exchange is made. We move on to compare the next pair without
any change to the list.
The 12 is larger than the 11 so they are exchanged.
The twelve is greater than the 9 so they are exchanged
The end of the list has been reached so this is the end of the first pass. The
twelve at the end of the list must be largest number in the list and so is now in
The 12
is greater
3 so
theypass
are exchanged.
the correct
position.
Wethan
now the
start
a new
from left to right.
The 12 is greater than the 7 so they are exchanged.
Bubble Sort Example
First Pass
6, 2, 9, 11, 9, 3, 7, 12
Second Pass
6, 6,
2,
2, 9, 9,
11, 3,
11,
9, 7,
11,
3, 11,
7, 12
Notice that this time we do not have to compare the last two
numbers as we know the 12 is in position. This pass therefore only
requires 6 comparisons.
Bubble Sort Example
First Pass
6, 2, 9, 11, 9, 3, 7, 12
Second Pass
2,
6,
9,
9,
3,
7,
11,
12
Third Pass
2, 6, 9, 3,
9, 9,
7, 9,
3,
7, 11, 12
This time the 11 and 12 are in position. This pass therefore only
requires 5 comparisons.
Bubble Sort Example
First Pass
6, 2, 9, 11, 9, 3, 7, 12
Second Pass
2,
6,
9,
9,
3,
7,
11,
12
Third Pass
2,
6,
9,
3,
7,
9,
11,
12
Fourth Pass
2, 6, 3,
9, 9,
7, 9,
3,
7, 9, 11, 12
Each pass requires fewer comparisons. This time only 4 are needed.
Bubble Sort Example
First Pass
6, 2, 9, 11, 9, 3, 7, 12
Second Pass
2,
Third Pass
2,
Fourth Pass
2,
Fifth Pass
2,
6,
6,
6,
6,
3,
9,
9,
3,
3,
6,
9,
3,
7,
7,
3,
7,
9,
9,
7,
9,
9,
9,
11,
11,
11,
11,
12
12
12
12
The list is now sorted but the algorithm does not know this until it
completes a pass with no exchanges.
Bubble Sort Example
First Pass
6, 2, 9, 11, 9, 3, 7, 12
Second Pass
2,
Third Pass
2,
Fourth Pass
2,
Fifth Pass
2,
Sixth Pass
2,
6,
6,
6,
3,
3,
9,
9,
3,
6,
6,
9,
3,
7,
7,
7,
3,
7,
9,
9,
9,
7,
9,
9,
9,
9,
11,
11,
11,
11,
11,
12
12
12
12
12
This pass no exchanges are made so the algorithm knows the list is
sorted. It can therefore save time by not doing the final pass. With
other lists this check could save much more work.
Bubble Sort Example
Quiz Time
1. Which number is definitely in its correct position at the
end of the first pass?
Answer: The last number must be the largest.
2. How does the number of comparisons required change as
the pass number increases?
Answer: Each pass requires one fewer comparison than the last.
3. How does the algorithm know when the list is sorted?
Answer: When a pass with no exchanges occurs.
4. What is the maximum number of comparisons required
for a list of 10 numbers?
Answer: 9 comparisons, then 8, 7, 6, 5, 4, 3, 2, 1 so total 45
Bubble Sort: Example
1
40
43
65
40
43
-1 58
40
-1 43
-1 40
-1 58
42
42
65
42
58 65
42
43 58 65
Notice that at least one element will be in the correct
position each iteration.
Bubble Sort: Example
5
-1
40
-1
40 42 43 58 65
-1
40 42 43 58 65
-1
40 42 43 58 65
42 43 58 65
Bubble Sort: Analysis
Running time:
Worst case: O(N2)
Best case: O(N)
Variant:
bi-directional bubble sort
original bubble sort: only works to one direction
bi-directional bubble sort: works back and forth.
Bubble Sort: Code
for (i = 0 ; i < ( n - 1 ); i++) {
for (j = n - 1 ; j > i; j--) {
if (array[j] > array[j-1]) {
swap (&array[j], &array[j-1]);
}
}
}
Selection Sort: Idea
1. We have two group of items:
sorted group, and
unsorted group
2. Initially, all items are in the unsorted group. The
sorted group is empty.
We assume that items in the unsorted group unsorted.
We have to keep items in the sorted group sorted.
Selection Sort: Contd
1.
2.
Select the best (eg. smallest) item from the
unsorted group, then put the best item at the end
of the sorted group.
Repeat the process until the unsorted group
becomes empty.
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
Largest
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
Largest
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
Largest
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
Largest
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
1
Comparison
Data Movement
Sorted
Selection Sort
Largest
Comparison
Data Movement
Sorted
Selection Sort
2
Comparison
Data Movement
Sorted
Selection Sort
DONE!
Comparison
Data Movement
Sorted
Selection
Sort:
Example
40 2 1 43 3 65 0 -1 58 3
42
40
43
-1 58
42 65
40
43
-1 42
58 65
40
-1 42 43 58 65
Selection Sort: Example
40
-1 42 43 58 65
-1
40 42 43 58 65
-1
40 42 43 58 65
-1
40 42 43 58 65
Selection Sort: Example
-1
40 42 43 58 65
-1
40 42 43 58 65
-1
40 42 43 58 65
-1
40 42 43 58 65
-1
40 42 43 58 65
Selection Sort: Analysis
Running time:
Worst case: O(N2)
Best case: O(N2)
Selection
Sort: Code
For (i=0;i<N-1;i++){
pos = i;
for(j=i+1;j<N;j++){
if ( arr[pos] > arr[j] )
pos = j;}
if(pos != i )
{ swap(&arr[i],&arr[p]); }
}
Mergesort
Mergesort (divide-and-conquer)
Divide array into two halves.
A
A
L
L
R
R
T
I
H
T
M
H
S
M
divide
Mergesort
Mergesort (divide-and-conquer)
Divide array into two halves.
Recursively sort each half.
A
divide
sort
Mergesort
Mergesort (divide-and-conquer)
Divide array into two halves.
Recursively sort each half.
Merge two halves to make sorted whole.
A
divide
sort
merge
Merging
Merge.
Keep track of smallest element in each sorted half.
Insert smallest of two elements into auxiliary array.
Repeat until done.
smallest
smallest
T
auxiliary array
Merging
Merge.
Keep track of smallest element in each sorted half.
Insert smallest of two elements into auxiliary array.
Repeat until done.
smallest
smallest
T
auxiliary array
Merging
Merge.
Keep track of smallest element in each sorted half.
Insert smallest of two elements into auxiliary array.
Repeat until done.
smallest
smallest
T
auxiliary array
Merging
Merge.
Keep track of smallest element in each sorted half.
Insert smallest of two elements into auxiliary array.
Repeat until done.
smallest
smallest
T
auxiliary array
Merging
Merge.
Keep track of smallest element in each sorted half.
Insert smallest of two elements into auxiliary array.
Repeat until done.
smallest
smallest
T
auxiliary array
Merging
Merge.
Keep track of smallest element in each sorted half.
Insert smallest of two elements into auxiliary array.
Repeat until done.
smallest
smallest
T
auxiliary array
Merging
Merge.
Keep track of smallest element in each sorted half.
Insert smallest of two elements into auxiliary array.
Repeat until done.
smallest
smallest
T
auxiliary array
Merging
Merge.
Keep track of smallest element in each sorted half.
Insert smallest of two elements into auxiliary array.
Repeat until done.
smallest
smallest
T
auxiliary array
Merging
Merge.
Keep track of smallest element in each sorted half.
Insert smallest of two elements into auxiliary array.
Repeat until done.
first half
exhausted
smallest
T
auxiliary array
Merging
Merge.
Keep track of smallest element in each sorted half.
Insert smallest of two elements into auxiliary array.
Repeat until done.
first half
exhausted
smallest
auxiliary array