Lecture No.05
Data Structures
Muhammad Rehman
Divide and Conquer
• Using this method each recursive subproblem is
about one-half the size of the original problem
• If we could define power so that each subproblem
was based on computing kn/2
instead of kn – 1
we
could use the divide and conquer principle
• Recursive divide and conquer algorithms are often
more efficient than iterative algorithms
Evaluating Exponents Using
Divide and Conquer
int power(int k, int n) {
// raise k to the power n
if (n == 0)
return 1;
else{
int t = power(k, n/2);
if ((n % 2) == 0)
return t * t;
else
return k * t * t;
}
Stacks
• Every recursive function can be
implemented using a stack and iteration.
• Every iterative function which uses a stack
can be implemented using recursion.
Disadvantages
• May run slower.
– Compilers
– Inefficient Code
• May use more space.
Advantages
• More natural.
• Easier to prove correct.
• Easier to analysis.
• More flexible.
Divide and Conquer
What if we split the list into two parts?
10 12 8 4 2 11 7 5
10 12 8 4 2 11 7 5
Divide and Conquer
Sort the two parts:
10 12 8 4 2 11 7 5
4 8 10 12 2 5 7 11
Divide and Conquer
Then merge the two parts together:
4 8 10 12 2 5 7 11
2 4 5 7 8 10 11 12
Analysis
• To sort the halves  (n/2)2
+(n/2)2
• To merge the two halves  n
• So, for n=100, divide and conquer takes:
= (100/2)2
+ (100/2)2
+ 100
= 2500 + 2500 + 100
= 5100 (n2
= 10,000)
Divide and Conquer
• Why not divide the halves in half?
• The quarters in half?
• And so on . . .
• When should we stop?
At n = 1
Search
Search
Divide and Conquer
Search
Search
Searc
Searc
h
h
Recall: Binary
Search
Sort
Sort
Divide and Conquer
Sort
Sort Sort
Sort
Sor
Sor
t
t
Sor
Sor
t
t
Sor
Sor
t
t
Sor
Sor
t
t
Divide and Conquer
Combine
Combine
Combine
Combine Combine
Combine
Mergesort
• Mergesort is a divide and conquer algorithm
that does exactly that.
• It splits the list in half
• Mergesorts the two halves
• Then merges the two sorted halves together
• Mergesort can be implemented recursively
Mergesort
• The mergesort algorithm involves three
steps:
– If the number of items to sort is 0 or 1, return
– Recursively sort the first and second halves
separately
– Merge the two sorted halves into a sorted group
Merging: animation
4 8 10 12 2 5 7 11
2
Merging: animation
4 8 10 12 2 5 7 11
2 4
Merging: animation
4 8 10 12 2 5 7 11
2 4 5
Merging
4 8 10 12 2 5 7 11
2 4 5 7
Mergesort
8 12 11 2 7 5
4
10
Split the list in half.
8 12
4
10
Mergesort the left half.
Split the list in half. Mergesort the left half.
4
10
Split the list in half. Mergesort the left half.
10
Mergesort the right.
4
Mergesort
8 12 11 2 7 5
4
10
8 12
4
10
4
10
Mergesort the right half.
Merge the two halves.
10
4 8 12
12
8
Merge the two halves.
8
8 12
Mergesort
8 12 11 2 7 5
4
10
8 12
4
10
Merge the two halves.
4
10
Mergesort the right half. Merge the two halves.
10
4 8 12
10 12
8
4
10
4 8 12
Mergesort
10 12 11 2 7 5
8
4
Mergesort the right half.
11 2 7 5
11 2
11 2
Mergesort
10 12 11 2 7 5
8
4
Mergesort the right half.
11 2 7 5
11 2
2 11
2 11
Mergesort
10 12 11 2 7 5
8
4
Mergesort the right half.
11 2 7 5
2 11
7
5
7 5
Mergesort
10 12 11 2 7 5
8
4
Mergesort the right half.
11 2 5
7
2 11
Mergesort
10 12 2 5 7 11
8
4
Mergesort the right half.
Mergesort
5 7 8 10 11 12
4
2
Merge the two halves.
void mergeSort(float array[], int size)
{
int* tmpArrayPtr = new int[size];
if (tmpArrayPtr != NULL)
mergeSortRec(array, size, tmpArrayPtr);
else
{
cout << “Not enough memory to sort list.n”);
return;
}
delete [] tmpArrayPtr;
}
Mergesort
void mergeSortRec(int array[],int size,int tmp[])
{
int i;
int mid = size/2;
if (size > 1){
mergeSortRec(array, mid, tmp);
mergeSortRec(array+mid, size-mid, tmp);
mergeArrays(array, mid, array+mid, size-mid,
tmp);
for (i = 0; i < size; i++)
array[i] = tmp[i];
}
}
Mergesort
3 5 15 28 30 6 10 14 22 43 50
a:
a: b:
b:
aSize: 5
aSize: 5 bSize: 6
bSize: 6
mergeArrays
tmp:
tmp:
mergeArrays
5 15 28 30 10 14 22 43 50
a:
a: b:
b:
tmp:
tmp:
i=0
i=0
k=0
k=0
j=0
j=0
3 6
mergeArrays
5 15 28 30 10 14 22 43 50
a:
a: b:
b:
tmp:
tmp:
i=0
i=0
k=0
k=0
3
j=0
j=0
3 6
mergeArrays
3 15 28 30 10 14 22 43 50
a:
a: b:
b:
tmp:
tmp:
i=1
i=1 j=0
j=0
k=1
k=1
3 5
5 6
mergeArrays
3 5 28 30 10 14 22 43 50
a:
a: b:
b:
3 5
tmp:
tmp:
i=2
i=2 j=0
j=0
k=2
k=2
6
15 6
mergeArrays
3 5 28 30 6 14 22 43 50
a:
a: b:
b:
3 5 6
tmp:
tmp:
i=2
i=2 j=1
j=1
k=3
k=3
15 10
10
10
mergeArrays
3 5 28 30 6 22 43 50
a:
a: b:
b:
3 5 6
tmp:
tmp:
i=2
i=2 j=2
j=2
k=4
k=4
15 10 14
14
14
10
mergeArrays
3 5 28 30 6 14 43 50
a:
a: b:
b:
3 5 6
tmp:
tmp:
i=2
i=2 j=3
j=3
k=5
k=5
15 10 22
15
14
10
mergeArrays
3 5 30 6 14 43 50
a:
a: b:
b:
3 5 6
tmp:
tmp:
i=3
i=3 j=3
j=3
k=6
k=6
15 10 22
22
15
28
14
10
mergeArrays
3 5 30 6 14 50
a:
a: b:
b:
3 5 6
tmp:
tmp:
i=3
i=3 j=4
j=4
k=7
k=7
15 10 22
28
15
28 43
22
14
10
mergeArrays
3 5 6 14 50
a:
a: b:
b:
3 5 6
tmp:
tmp:
i=4
i=4 j=4
j=4
k=8
k=8
15 10 22
30
15
28 43
22
30
28
14
10
mergeArrays
3 5 6 14 50
a:
a: b:
b:
3 5 6 30
tmp:
tmp:
i=5
i=5 j=4
j=4
k=9
k=9
15 10 22
15
28 43
22
30
28 43 50
Done.
Merge Sort and Linked Lists
Sort Sort
Merg
e
Mergesort Analysis
Merging the two lists of size n/2:
O(n)
Merging the four lists of size n/4:
O(n)
.
.
.
Merging the n lists of size 1:
O(n)
O (lg n)
times
 Mergesort is O(n lg n)
 Space?
 The other sorts we have looked at (insertion,
selection) are in-place (only require a constant
amount of extra space)
 Mergesort requires O(n) extra space for merging
Mergesort Analysis
• Mergesort is O(n lg n)
• Space?
• The other sorts we have looked at
(insertion, selection) are in-place (only
require a constant amount of extra space)
• Mergesort requires O(n) extra space for
merging
Quicksort
• Quicksort is another divide and conquer
algorithm
• Quicksort is based on the idea of
partitioning (splitting) the list around a
pivot or split value
Quicksort
First the list is partitioned around a pivot
value. Pivot can be chosen from the beginning,
end or middle of list):
8 3
2 11 7
5
4 10
12
4 5
5
pivot value
Quicksort
The pivot is swapped to the last position and
the
remaining elements are compared starting at
the
ends.
8 3 2 11 7 5
4 10
12
4 5
low high
5
pivot value
Quicksort
Then the low index moves right until it is at an
element
that is larger than the pivot value (i.e., it is on the
wrong side)
8 6 2 11 7 5
10
12
4 6
low high
5
pivot value
3
12
Quicksort
Then the high index moves left until it is at an
element that is smaller than the pivot value (i.e., it
is on the wrong side)
8 6 2 11 7 5
4 10
12
4 6
low high
5
pivot value
3 2
Quicksort
Then the two values are swapped and the
index values are updated:
8 6 2 11 7 5
4 10
12
4 6
low high
5
pivot value
3
2 12
Quicksort
This continues until the two index values pass
each other:
8 6 12 11 7 5
4
2
4 6
low high
5
pivot value
3
10
3 10
Quicksort
This continues until the two index values pass
each other:
8 6 12 11 7 5
4
2
4 6
low
high
5
pivot value
10
3
Quicksort
Then the pivot value is swapped into position:
8 6 12 11 7 5
4
2
4 6
low
high
10
3 8
5
Quicksort
Recursively quicksort the two parts:
5 6 12 11 7 8
4
2
4 6
10
3
Quicksort the left part Quicksort the right part
5
void quickSort(int array[], int size)
{
int index;
if (size > 1)
{
index = partition(array, size);
quickSort(array, index);
quickSort(array+index+1, size - index-1);
}
}
Quicksort
int partition(int array[], int size)
{
int k;
int mid = size/2;
int index = 0;
swap(array, array+mid);
for (k = 1; k < size; k++){
if (array[k] < array[0]){
index++;
swap(array+k, array+index);
}
}
swap(array, array+index);
return index;
}
Quicksort

Lec 6 Divide and conquer of Data Structures & Algortihms

  • 1.
  • 2.
    Divide and Conquer •Using this method each recursive subproblem is about one-half the size of the original problem • If we could define power so that each subproblem was based on computing kn/2 instead of kn – 1 we could use the divide and conquer principle • Recursive divide and conquer algorithms are often more efficient than iterative algorithms
  • 3.
    Evaluating Exponents Using Divideand Conquer int power(int k, int n) { // raise k to the power n if (n == 0) return 1; else{ int t = power(k, n/2); if ((n % 2) == 0) return t * t; else return k * t * t; }
  • 4.
    Stacks • Every recursivefunction can be implemented using a stack and iteration. • Every iterative function which uses a stack can be implemented using recursion.
  • 5.
    Disadvantages • May runslower. – Compilers – Inefficient Code • May use more space.
  • 6.
    Advantages • More natural. •Easier to prove correct. • Easier to analysis. • More flexible.
  • 7.
    Divide and Conquer Whatif we split the list into two parts? 10 12 8 4 2 11 7 5 10 12 8 4 2 11 7 5
  • 8.
    Divide and Conquer Sortthe two parts: 10 12 8 4 2 11 7 5 4 8 10 12 2 5 7 11
  • 9.
    Divide and Conquer Thenmerge the two parts together: 4 8 10 12 2 5 7 11 2 4 5 7 8 10 11 12
  • 10.
    Analysis • To sortthe halves  (n/2)2 +(n/2)2 • To merge the two halves  n • So, for n=100, divide and conquer takes: = (100/2)2 + (100/2)2 + 100 = 2500 + 2500 + 100 = 5100 (n2 = 10,000)
  • 11.
    Divide and Conquer •Why not divide the halves in half? • The quarters in half? • And so on . . . • When should we stop? At n = 1
  • 12.
  • 13.
    Sort Sort Divide and Conquer Sort SortSort Sort Sor Sor t t Sor Sor t t Sor Sor t t Sor Sor t t
  • 14.
  • 15.
    Mergesort • Mergesort isa divide and conquer algorithm that does exactly that. • It splits the list in half • Mergesorts the two halves • Then merges the two sorted halves together • Mergesort can be implemented recursively
  • 16.
    Mergesort • The mergesortalgorithm involves three steps: – If the number of items to sort is 0 or 1, return – Recursively sort the first and second halves separately – Merge the two sorted halves into a sorted group
  • 17.
    Merging: animation 4 810 12 2 5 7 11 2
  • 18.
    Merging: animation 4 810 12 2 5 7 11 2 4
  • 19.
    Merging: animation 4 810 12 2 5 7 11 2 4 5
  • 20.
    Merging 4 8 1012 2 5 7 11 2 4 5 7
  • 21.
    Mergesort 8 12 112 7 5 4 10 Split the list in half. 8 12 4 10 Mergesort the left half. Split the list in half. Mergesort the left half. 4 10 Split the list in half. Mergesort the left half. 10 Mergesort the right. 4
  • 22.
    Mergesort 8 12 112 7 5 4 10 8 12 4 10 4 10 Mergesort the right half. Merge the two halves. 10 4 8 12 12 8 Merge the two halves. 8 8 12
  • 23.
    Mergesort 8 12 112 7 5 4 10 8 12 4 10 Merge the two halves. 4 10 Mergesort the right half. Merge the two halves. 10 4 8 12 10 12 8 4 10 4 8 12
  • 24.
    Mergesort 10 12 112 7 5 8 4 Mergesort the right half. 11 2 7 5 11 2 11 2
  • 25.
    Mergesort 10 12 112 7 5 8 4 Mergesort the right half. 11 2 7 5 11 2 2 11 2 11
  • 26.
    Mergesort 10 12 112 7 5 8 4 Mergesort the right half. 11 2 7 5 2 11 7 5 7 5
  • 27.
    Mergesort 10 12 112 7 5 8 4 Mergesort the right half. 11 2 5 7 2 11
  • 28.
    Mergesort 10 12 25 7 11 8 4 Mergesort the right half.
  • 29.
    Mergesort 5 7 810 11 12 4 2 Merge the two halves.
  • 30.
    void mergeSort(float array[],int size) { int* tmpArrayPtr = new int[size]; if (tmpArrayPtr != NULL) mergeSortRec(array, size, tmpArrayPtr); else { cout << “Not enough memory to sort list.n”); return; } delete [] tmpArrayPtr; } Mergesort
  • 31.
    void mergeSortRec(int array[],intsize,int tmp[]) { int i; int mid = size/2; if (size > 1){ mergeSortRec(array, mid, tmp); mergeSortRec(array+mid, size-mid, tmp); mergeArrays(array, mid, array+mid, size-mid, tmp); for (i = 0; i < size; i++) array[i] = tmp[i]; } } Mergesort
  • 32.
    3 5 1528 30 6 10 14 22 43 50 a: a: b: b: aSize: 5 aSize: 5 bSize: 6 bSize: 6 mergeArrays tmp: tmp:
  • 33.
    mergeArrays 5 15 2830 10 14 22 43 50 a: a: b: b: tmp: tmp: i=0 i=0 k=0 k=0 j=0 j=0 3 6
  • 34.
    mergeArrays 5 15 2830 10 14 22 43 50 a: a: b: b: tmp: tmp: i=0 i=0 k=0 k=0 3 j=0 j=0 3 6
  • 35.
    mergeArrays 3 15 2830 10 14 22 43 50 a: a: b: b: tmp: tmp: i=1 i=1 j=0 j=0 k=1 k=1 3 5 5 6
  • 36.
    mergeArrays 3 5 2830 10 14 22 43 50 a: a: b: b: 3 5 tmp: tmp: i=2 i=2 j=0 j=0 k=2 k=2 6 15 6
  • 37.
    mergeArrays 3 5 2830 6 14 22 43 50 a: a: b: b: 3 5 6 tmp: tmp: i=2 i=2 j=1 j=1 k=3 k=3 15 10 10
  • 38.
    10 mergeArrays 3 5 2830 6 22 43 50 a: a: b: b: 3 5 6 tmp: tmp: i=2 i=2 j=2 j=2 k=4 k=4 15 10 14 14
  • 39.
    14 10 mergeArrays 3 5 2830 6 14 43 50 a: a: b: b: 3 5 6 tmp: tmp: i=2 i=2 j=3 j=3 k=5 k=5 15 10 22 15
  • 40.
    14 10 mergeArrays 3 5 306 14 43 50 a: a: b: b: 3 5 6 tmp: tmp: i=3 i=3 j=3 j=3 k=6 k=6 15 10 22 22 15 28
  • 41.
    14 10 mergeArrays 3 5 306 14 50 a: a: b: b: 3 5 6 tmp: tmp: i=3 i=3 j=4 j=4 k=7 k=7 15 10 22 28 15 28 43 22
  • 42.
    14 10 mergeArrays 3 5 614 50 a: a: b: b: 3 5 6 tmp: tmp: i=4 i=4 j=4 j=4 k=8 k=8 15 10 22 30 15 28 43 22 30 28
  • 43.
    14 10 mergeArrays 3 5 614 50 a: a: b: b: 3 5 6 30 tmp: tmp: i=5 i=5 j=4 j=4 k=9 k=9 15 10 22 15 28 43 22 30 28 43 50 Done.
  • 44.
    Merge Sort andLinked Lists Sort Sort Merg e
  • 45.
    Mergesort Analysis Merging thetwo lists of size n/2: O(n) Merging the four lists of size n/4: O(n) . . . Merging the n lists of size 1: O(n) O (lg n) times  Mergesort is O(n lg n)  Space?  The other sorts we have looked at (insertion, selection) are in-place (only require a constant amount of extra space)  Mergesort requires O(n) extra space for merging
  • 46.
    Mergesort Analysis • Mergesortis O(n lg n) • Space? • The other sorts we have looked at (insertion, selection) are in-place (only require a constant amount of extra space) • Mergesort requires O(n) extra space for merging
  • 47.
    Quicksort • Quicksort isanother divide and conquer algorithm • Quicksort is based on the idea of partitioning (splitting) the list around a pivot or split value
  • 48.
    Quicksort First the listis partitioned around a pivot value. Pivot can be chosen from the beginning, end or middle of list): 8 3 2 11 7 5 4 10 12 4 5 5 pivot value
  • 49.
    Quicksort The pivot isswapped to the last position and the remaining elements are compared starting at the ends. 8 3 2 11 7 5 4 10 12 4 5 low high 5 pivot value
  • 50.
    Quicksort Then the lowindex moves right until it is at an element that is larger than the pivot value (i.e., it is on the wrong side) 8 6 2 11 7 5 10 12 4 6 low high 5 pivot value 3 12
  • 51.
    Quicksort Then the highindex moves left until it is at an element that is smaller than the pivot value (i.e., it is on the wrong side) 8 6 2 11 7 5 4 10 12 4 6 low high 5 pivot value 3 2
  • 52.
    Quicksort Then the twovalues are swapped and the index values are updated: 8 6 2 11 7 5 4 10 12 4 6 low high 5 pivot value 3 2 12
  • 53.
    Quicksort This continues untilthe two index values pass each other: 8 6 12 11 7 5 4 2 4 6 low high 5 pivot value 3 10 3 10
  • 54.
    Quicksort This continues untilthe two index values pass each other: 8 6 12 11 7 5 4 2 4 6 low high 5 pivot value 10 3
  • 55.
    Quicksort Then the pivotvalue is swapped into position: 8 6 12 11 7 5 4 2 4 6 low high 10 3 8 5
  • 56.
    Quicksort Recursively quicksort thetwo parts: 5 6 12 11 7 8 4 2 4 6 10 3 Quicksort the left part Quicksort the right part 5
  • 57.
    void quickSort(int array[],int size) { int index; if (size > 1) { index = partition(array, size); quickSort(array, index); quickSort(array+index+1, size - index-1); } } Quicksort
  • 58.
    int partition(int array[],int size) { int k; int mid = size/2; int index = 0; swap(array, array+mid); for (k = 1; k < size; k++){ if (array[k] < array[0]){ index++; swap(array+k, array+index); } } swap(array, array+index); return index; } Quicksort

Editor's Notes

  • #4 Visit: tshahab.blogspot.com
  • #6 Visit: tshahab.blogspot.com
  • #9 End of lecture 44.
  • #10 Start of lecture 45
  • #57 End of lecture 45. At last!