Upload
victor-quentin-bennett
View
220
Download
2
Tags:
Embed Size (px)
Citation preview
CSCS-200 Data Structure and Algorithms
Lecture-26-27-28
2
Inserting into a Heap
insert(15) with exchange
13
16
21
3126
24
65 32
6819
13 2116 24 3119 68 65 26 32
1 2 3 4 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
14
14
11
15
1512
3
Inserting into a Heap
insert(15) with exchange
13
16
21
3126
24
65 32
68
19
13 2116 24 31 1968 65 26 32
1 2 3 4 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
14
14
11
15
15
12
4
Inserting into a Heap
insert(15) with exchange
13
1621
3126
24
65 32
68
19
13 21 1624 31 1968 65 26 32
1 2 3 4 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
14
14
11
15
15
12
5
Inserting into a Heap
insert(15) with exchange
13
1621
3126
24
65 32
68
19
13 21 1624 31 1968 65 26 32
1 2 3 4 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
14
14
11
15
15
12
6
DeleteMin
• Finding the minimum is easy; it is at the top of the heap.• Deleting it (or removing it) causes a hole which needs to
be filled.
13
16
21
3126
24
65 32
6819
1
2 3
7654
8 9 10
14
11
7
DeleteMin
deleteMin()
16
21
3126
24
65 32
6819
1
2 3
7654
8 9 10
14
11
8
DeleteMin
deleteMin()
14
16
21
3126
24
65 32
6819
1
2 3
7654
8 9 10 11
9
DeleteMin
deleteMin()
14
16
3126
24
65 32
6819
1
2 3
7654
8 9 10
21
11
10
DeleteMin
deleteMin()
14
16
31
26
24
65 32
6819
1
2 3
7654
8 9 10
21
11
11
DeleteMin
deleteMin(): heap size is reduced by 1.
14
16
31
26
24
65 32
6819
1
2 3
7654
8 9 10
21
12
BuildHeap
• Suppose we are given as input N keys (or items) and we want to build a heap of the keys.
• Obviously, this can be done with N successive inserts.
• Each call to insert will either take unit time (leaf node) or log2N (if new key percolates all the way up to the root).
13
BuildHeap
• The worst time for building a heap of N keys could be Nlog2N.
• It turns out that we can build a heap in linear time.
14
BuildHeap
• Suppose we have a method percolateDown(p) which moves down the key in node p downwards.
• This is what was happening in deleteMin.
15
BuildHeap
Initial data (N=15)
65 21 1926 14 1668 13 24 15
1 2 3 5 6 7 8 9 10 11 12 13 140
31 32
154
5 70 12
16
BuildHeap
Initial data (N=15) 65
1921
1424
26
13 15
68
16
65 21 1926 14 1668 13 24 15
1 2 3 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
31
31
11
32
32
12
154
513 7014 1215
5 70 12
17
BuildHeap
• The general algorithm is to place the N keys in an array and consider it to be an unordered binary tree.
• The following algorithm will build a heap out of N keys.
for( i = N/2; i > 0; i-- )
percolateDown(i);
18
BuildHeap
i = 15/2 = 7 65
1921
1424
26
13 15
68
16
65 21 1926 14 1668 13 24 15
1 2 3 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
31
31
11
32
32
12
154
513 7014 1215
5 70 12
i
i
Why I=n/2?
19
BuildHeap
i = 15/2 = 7 65
1921
1424
26
13 15
12
16
65 21 1926 14 1612 13 24 15
1 2 3 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
31
31
11
32
32
12
154
513 7014 6815
5 70 68
i
i
20
BuildHeap
i = 6 65
1921
1424
26
13 15
12
16
65 21 1926 14 1612 13 24 15
1 2 3 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
31
31
11
32
32
12
154
513 7014 6815
5 70 68
i
i
21
BuildHeap
i = 5 65
521
1424
26
13 15
12
16
65 21 526 14 1612 13 24 15
1 2 3 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
31
31
11
32
32
12
154
1913 7014 6815
19 70 68
i
i
22
BuildHeap
i = 4 65
514
2124
26
13 15
12
16
65 14 526 21 1612 13 24 15
1 2 3 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
31
31
11
32
32
12
154
1913 7014 6815
19 70 68
i
i
23
BuildHeap
i = 3 65
514
2124
13
26 15
12
16
65 14 513 21 1612 26 24 15
1 2 3 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
31
31
11
32
32
12
154
1913 7014 6815
19 70 68
i
i
24
BuildHeap
i = 2 65
1614
2124
13
26 15
12
32
65 14 1613 21 3212 26 24 15
1 2 3 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
31
31
11
5
5
12
154
1913 7014 6815
19 70 68
i
i
25
BuildHeap
i = 1 65
1614
2131
24
26 15
12
32
65 14 1624 21 3212 26 31 15
1 2 3 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
13
13
11
5
5
12
154
1913 7014 6815
19 70 68
i
i
26
BuildHeap
Min heap 5
1614
2131
24
26 15
65
32
5 14 1624 21 3265 26 31 15
1 2 3 5 6 7 8 9 10 11 12 13 140
1
2 3
7654
8 9 10
13
13
11
12
12
12
154
1913 7014 6815
19 70 68
27
Other Heap Operations
• decreaseKey(p, delta): lowers the value of the key at position ‘p’ by the amount ‘delta’. Since this might violate the heap order, the heap must be reorganized with percolate up (in min heap) or down (in max heap).
• increaseKey(p, delta): opposite of decreaseKey.
• remove(p): removes the node at position p from the heap. This is done by first decreaseKey(p, ) and then performing deleteMin().
28
Heap code in C++
template <class eType>class Heap{ public: Heap( int capacity = 100 );
void insert( const eType & x ); void deleteMin( eType & minItem ); const eType & getMin( );
bool isEmpty( ); bool isFull( ); int Heap<eType>::getSize( );
29
Heap code in C++
private: int currentSize; // Number of elements in heap eType* array; // The heap array int capacity; void percolateDown( int hole );};
30
Heap code in C++
#include "Heap.h“
template <class eType>Heap<eType>::Heap( int capacity ){ array = new etype[capacity + 1]; currentSize=0;}
31
Heap code in C++
// Insert item x into the heap, maintaining heap// order. Duplicates are allowed.template <class eType>bool Heap<eType>::insert( const eType & x ){ if( isFull( ) ) { cout << "insert - Heap is full." << endl; return 0; } // Percolate up int hole = ++currentSize; for(; hole > 1 && x < array[hole/2 ]; hole /= 2) array[ hole ] = array[ hole / 2 ]; array[hole] = x;}
32
Heap code in C++
template <class eType>void Heap<eType>::deleteMin( eType & minItem ){ if( isEmpty( ) ) { cout << "heap is empty.“ << endl;
return; }
minItem = array[ 1 ]; array[ 1 ] = array[ currentSize-- ]; percolateDown( 1 );}
33
Heap code in C++
// hole is the index at which the percolate begins.template <class eType>void Heap<eType>::percolateDown( int hole ){ int child; eType tmp = array[ hole ]; for( ; hole * 2 <= currentSize; hole = child ) { child = hole * 2; if( child != currentSize && array[child+1] < array[ child ] ) child++; // right child is smaller if( array[ child ] < tmp ) array[ hole ] = array[ child ]; else break; } array[ hole ] = tmp;}
34
Heap code in C++
template <class eType>const eType& Heap<eType>::getMin( ){ if( !isEmpty( ) ) return array[ 1 ];}
template <class eType>void Heap<eType>::buildHeap(eType* anArray, int n ){ for(int i = 1; i <= n; i++) array[i] = anArray[i-1]; currentSize = n; for( int i = currentSize / 2; i > 0; i-- ) percolateDown( i );}
35
Heap code in C++
template <class eType>bool Heap<eType>::isEmpty( ){ return currentSize == 0;}template <class eType>bool Heap<eType>::isFull( ){ return currentSize == capacity;}template <class eType>int Heap<eType>::getSize( ){ return currentSize;}
36
BuildHeap in Linear Time
• How is buildHeap a linear time algorithm? I.e., better than Nlog2N?
• We need to show that the sum of heights is a linear function of N (number of nodes).
Theorem: For a perfect binary tree of height h containing 2h +1 – 1 nodes, the sum of the heights of nodes is 2h +1 – 1 – (h +1), or N-h-1.
37
BuildHeap in Linear Time
It is easy to see that this tree consists of (20) node at height h, 21 nodes at height h –1, 22 at h-2 and, in general, 2i nodes at h – i.
38
Complete Binary Tree
A
B
h : 20 nodes
H
D
I
E
J K
C
L
F
M
G
N O
h -1: 21 nodes
h -2: 22 nodes
h -3: 23 nodes
39
BuildHeap in Linear Time
The sum of the heights of all the nodes is then
S = 2i(h – i), for i = 0 to h-1
= h + 2(h-1) + 4(h-2) + 8(h-3)+ ….. + 2h-1 (1)
Multiplying by 2 gives the equation2S = 2h + 4(h-1) + 8(h-2) + 16(h-3)+ ….. + 2h (2)
Subtract the two equations to getS = -h + 2 + 4 + 8 + 16+ ….. + 2h-1 +2h
= (2h+1 – 1) - (h+1)
Which proves the theorem.
40
BuildHeap in Linear Time
Since a complete binary tree has between 2h
and 2h+1 nodes
S = (2h+1 – 1) - (h+1) N - log2(N+1)
Clearly, as N gets larger, the log2(N +1) term becomes insignificant and S becomes a function of N.
41
BuildHeap in Linear Time
• Another way to prove the theorem.• The height of a node in the tree = the number of
edges on the longest downward path to a leaf • The height of a tree = the height of its root• For any node in the tree that has some height h,
darken h tree edges– Go down tree by traversing left edge then only
right edges• There are N – 1 tree edges, and h edges on right
path, so number of darkened edges is N – 1 – h, which proves the theorem.
42
Height 1 Nodes
Marking the left edges for height 1 nodes
43
Height 2 Nodes
Marking the first left edge and the subsequent right edge for height 2 nodes
44
Height 3 Nodes
Marking the first left edge and the subsequent two right edges for height 3 nodes
45
Height 4 Nodes
Marking the first left edge and the subsequent three right edges for height 4 nodes
46
Theorem
N=31, treeEdges=30, H=4, dottedEdges=4 (H).Darkened Edges = 26 = N-H-1 (31-4-1)
47
The Selection Problem
• Given a list of N elements (numbers, names etc.), which can be totally ordered, and an integer k, find the kth smallest (or largest) element.
• One way is to put these N elements in an array an sort it. The kth smallest of these is at the kth position.
48
The Selection Problem
• A faster way is to put the N elements into an array and apply the buildHeap algorithm on this array.
• Finally, we perform k deleteMin operations. The last element extracted from the heap is our answer.
• The interesting case is k = N/2, since this is known as the median.
49
HeapSort
• If k = N, and we record the deleteMin elements as they come off the heap, we will have essentially sorted the N elements.
• Later in the course, we will refine this idea to obtain a fast sorting algorithm called heapsort.
50
• An array in which TableNodes are not stored consecutively
• Their place of storage is calculated using the key and a hash function
• Keys and entries are scattered throughout the array.
Implementation 6: Hashing
key entry
Key hash function
array index
4
10
123
51
• insert: calculate place of storage, insert TableNode; (1)
• find: calculate place of storage, retrieve entry; (1)
• remove: calculate place of storage, set it to null; (1)
Hashing
key entry
4
10
123All are constant time (1) !
52
Hashing
• We use an array of some fixed size T to hold the data. T is typically prime.
• Each key is mapped into some number in the range 0 to T-1 using a hash function, which ideally should be efficient to compute.
53
Example: fruits
• Suppose our hash function gave us the following values: hashCode("apple") = 5
hashCode("watermelon") = 3hashCode("grapes") = 8hashCode("cantaloupe") = 7hashCode("kiwi") = 0hashCode("strawberry") = 9hashCode("mango") = 6hashCode("banana") = 2
kiwi
bananawatermelon
applemango
cantaloupegrapes
strawberry
0
1
2
3
4
5
6
7
8
9
54
Example
• Store data in a table array: table[5] = "apple"
table[3] = "watermelon" table[8] = "grapes" table[7] = "cantaloupe" table[0] = "kiwi" table[9] = "strawberry" table[6] = "mango" table[2] = "banana"
kiwi
bananawatermelon
applemango
cantaloupegrapes
strawberry
0
1
2
3
4
5
6
7
8
9
55
Example
• Associative array: table["apple"]
table["watermelon"] table["grapes"] table["cantaloupe"] table["kiwi"] table["strawberry"] table["mango"] table["banana"]
kiwi
bananawatermelon
applemango
cantaloupegrapes
strawberry
0
1
2
3
4
5
6
7
8
9
56
Example Hash Functions
• If the keys are strings the hash function is some function of the characters in the strings.
• One possibility is to simply add the ASCII values of the characters:
TableSizeABChExample
TableSizeistrstrhlength
i
)%676665()(:
%][)(1
0
57
Finding the hash function
int hashCode( char* s ){
int i, sum;sum = 0;for(i=0; i < strlen(s); i++ ) sum = sum + s[i]; // ascii value
return sum % TABLESIZE;
}
58
Example Hash Functions
• Another possibility is to convert the string into some number in some arbitrary base b (b also might be a prime number):
TbbbABChExample
Tbistrstrhlength
i
i
)%676665()(:
%][)(
210
1
0
59
Example Hash Functions
• If the keys are integers then key%T is generally a good hash function, unless the data has some undesirable features.
• For example, if T = 10 and all keys end in zeros, then key%T = 0 for all keys.
• In general, to avoid situations like this, T should be a prime number.
60
Collision
Suppose our hash function gave us the following values:
– hash("apple") = 5hash("watermelon") = 3hash("grapes") = 8hash("cantaloupe") = 7hash("kiwi") = 0hash("strawberry") = 9hash("mango") = 6hash("banana") = 2
kiwi
bananawatermelon
applemango
cantaloupegrapes
strawberry
0
1
2
3
4
5
6
7
8
9• Now what?
hash("honeydew") = 6
61
Collision
• When two values hash to the same array location, this is called a collision
• Collisions are normally treated as “first come, first served”—the first value that hashes to the location gets it
• We have to find something to do with the second and subsequent values that hash to this same location.
62
Solution for Handling collisions
• Solution #1: Search from there for an empty location– Can stop searching when we find the value or
an empty location.– Search must be wrap-around at the end.
63
Solution for Handling collisions
• Solution #2: Use a second hash function– ...and a third, and a fourth, and a fifth, ...
64
Solution for Handling collisions
• Solution #3: Use the array location as the header of a linked list of values that hash to this location
65
Solution 1: Open Addressing
• This approach of handling collisions is called open addressing; it is also known as closed hashing.
• More formally, cells at h0(x), h1(x), h2(x), … are tried in succession where
hi(x) = (hash(x) + f(i)) mod TableSize,
with f(0) = 0.• The function, f, is the collision resolution
strategy.
66
Linear Probing
• We use f(i) = i, i.e., f is a linear function of i. Thus
location(x) = (hash(x) + i) mod TableSize
• The collision resolution strategy is called linear probing because it scans the array sequentially (with wrap around) in search of an empty cell.
67
Linear Probing: insert
• Suppose we want to add seagull to this hash table
• Also suppose:– hashCode(“seagull”) = 143
– table[143] is not empty– table[143] != seagull
– table[144] is not empty– table[144] != seagull
– table[145] is empty
• Therefore, put seagull at location 145
robin
sparrow
hawk
bluejay
owl
. . .
141
142
143
144
145
146
147
148
. . .
seagull
68
Linear Probing: insert
• Suppose you want to add hawk to this hash table
• Also suppose– hashCode(“hawk”) = 143
– table[143] is not empty– table[143] != hawk
– table[144] is not empty– table[144] == hawk
• hawk is already in the table, so do nothing.
robin
sparrow
hawk
seagull
bluejay
owl
. . .
141
142
143
144
145
146
147
148
. . .
69
Linear Probing: insert
• Suppose:– You want to add cardinal to
this hash table– hashCode(“cardinal”) = 147
– The last location is 148– 147 and 148 are occupied
• Solution:– Treat the table as circular;
after 148 comes 0– Hence, cardinal goes in
location 0 (or 1, or 2, or ...)
robin
sparrow
hawk
seagull
bluejay
owl
. . .
141
142
143
144
145
146
147
148
70
Linear Probing: find
• Suppose we want to find hawk in this hash table
• We proceed as follows:– hashCode(“hawk”) = 143– table[143] is not empty– table[143] != hawk– table[144] is not empty– table[144] == hawk (found!)
• We use the same procedure for looking things up in the table as we do for inserting them
robin
sparrow
hawk
seagull
bluejay
owl
. . .
141
142
143
144
145
146
147
148
. . .
71
Linear Probing and Deletion
• If an item is placed in array[hash(key)+4], then the item just before it is deleted
• How will probe determine that the “hole” does not indicate the item is not in the array?
• Have three states for each location– Occupied– Empty (never used)– Deleted (previously used)
72
Clustering
• One problem with linear probing technique is the tendency to form “clusters”.
• A cluster is a group of items not containing any open slots
• The bigger a cluster gets, the more likely it is that new values will hash into the cluster, and make it ever bigger.
• Clusters cause efficiency to degrade.
73
Quadratic Probing
• Quadratic probing uses different formula:– Use F(i) = i2 to resolve collisions– If hash function resolves to H and a search in cell H is
inconclusive, try H + 12, H + 22, H + 32, …
• Probe array[hash(key)+12], thenarray[hash(key)+22], thenarray[hash(key)+32], and so on
– Virtually eliminates primary clusters
74
Collision resolution: chaining
• Each table position is a linked list
• Add the keys and entries anywhere in the list (front easiest)
4
10
123
key entry key entry
key entry key entry
key entry
No need to change position!
75
Collision resolution: chaining
• Advantages over open addressing:– Simpler insertion and
removal– Array size is not a
limitation • Disadvantage
– Memory overhead is large if entries are small.
4
10
123
key entry key entry
key entry key entry
key entry
76
Applications of Hashing
• Compilers use hash tables to keep track of declared variables (symbol table).
• A hash table can be used for on-line spelling checkers — if misspelling detection (rather than correction) is important, an entire dictionary can be hashed and words checked in constant time.
77
Applications of Hashing
• Game playing programs use hash tables to store seen positions, thereby saving computation time if the position is encountered again.
• Hash functions can be used to quickly check for inequality — if two elements hash to different values they must be different.
78
When is hashing suitable?
• Hash tables are very good if there is a need for many searches in a reasonably stable table.
• Hash tables are not so good if there are many insertions and deletions, or if table traversals are needed — in this case, AVL trees are better.
• Also, hashing is very slow for any operations which require the entries to be sorted– e.g. Find the minimum key
SORTING AGAIN !!!
80
Summary
• Insertion, Selection and Bubble sort: – Worst case time complexity is proportional to N2.
Best sorting routines are N log(N)
81
NLogN Algorithms
• Divide and Conquer• Merge Sort• Quick Sort• Heap Sort
82
Divide and Conquer
What if we split the list into two parts?
10 12 8 4 2 11 7 510 12 8 4 2 11 7 5
83
Divide and Conquer
Sort the two parts:
10 12 8 4 2 11 7 54 8 10 12 2 5 7 11
84
Divide and Conquer
Then merge the two parts together:
4 8 10 12 2 5 7 112 4 5 7 8 10 11 12
85
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)
86
Divide and Conquer
• Why not divide the halves in half?• The quarters in half?• And so on . . .• When should we stop?
At n = 1
87
SearchSearch
Divide and Conquer
SearchSearch
SearchSearch
Recall: Binary Search
88
SortSort
Divide and Conquer
SortSort SortSort
SortSort SortSort SortSort SortSort
89
Divide and Conquer
CombineCombine
CombineCombine CombineCombine
90
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
91
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
92
Merging: animation
4 8 10 12 2 5 7 11
2
93
Merging: animation
4 8 10 12 2 5 7 11
2 4
94
Merging: animation
4 8 10 12 2 5 7 11
2 4 5
95
Merging
4 8 10 12 2 5 7 11
2 4 5 7
96
Mergesort
8 12 11 2 7 5410
Split the list in half.
8 12410
Mergesort the left half.
Split the list in half. Mergesort the left half.
410
Split the list in half. Mergesort the left half.
10
Mergesort the right.
4
97
Mergesort
8 12 11 2 7 5410
8 12410
410
Mergesort the right half.
Merge the two halves.
104 8 12
128
Merge the two halves.
88 12
98
Mergesort
8 12 11 2 7 5410
8 12410
Merge the two halves.
410
Mergesort the right half. Merge the two halves.
104 8 12
10 1284
104 8 12
99
Mergesort
10 12 11 2 7 584
Mergesort the right half.
11 2 7 5
11 2
11 2
100
Mergesort
10 12 11 2 7 584
Mergesort the right half.
11 2 7 5
11 22 11
2 11
101
Mergesort
10 12 11 2 7 584
Mergesort the right half.
11 2 7 52 11
7 5
7 5
5 7
102
Mergesort
10 12 11 2 7 584
Mergesort the right half.
11 2 5 72 11
103
Mergesort
10 12 2 5 7 1184
Mergesort the right half.
104
Mergesort
5 7 8 10 11 1242
Merge the two halves.
105
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
106
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
107
3 5 15 28 30 6 10 14 22 43 50a:a: b:b:
aSize: 5aSize: 5 bSize: 6bSize: 6
mergeArrays
tmp:tmp:
108
mergeArrays
5 15 28 30 10 14 22 43 50a:a: b:b:
tmp:tmp:
i=0i=0
k=0k=0
j=0j=0
3 6
109
mergeArrays
5 15 28 30 10 14 22 43 50a:a: b:b:
tmp:tmp:
i=0i=0
k=0k=0
3
j=0j=0
3 6
110
mergeArrays
3 15 28 30 10 14 22 43 50a:a: b:b:
tmp:tmp:
i=1i=1 j=0j=0
k=1k=1
3 5
5 6
111
mergeArrays
3 5 28 30 10 14 22 43 50a:a: b:b:
3 5tmp:tmp:
i=2i=2 j=0j=0
k=2k=2
6
15 6
112
mergeArrays
3 5 28 30 6 14 22 43 50a:a: b:b:
3 5 6tmp:tmp:
i=2i=2 j=1j=1
k=3k=3
15 10
10
113
10
mergeArrays
3 5 28 30 6 22 43 50a:a: b:b:
3 5 6tmp:tmp:
i=2i=2 j=2j=2
k=4k=4
15 10 14
14
114
1410
mergeArrays
3 5 28 30 6 14 43 50a:a: b:b:
3 5 6tmp:tmp:
i=2i=2 j=3j=3
k=5k=5
15 10 22
15
115
1410
mergeArrays
3 5 30 6 14 43 50a:a: b:b:
3 5 6tmp:tmp:
i=3i=3 j=3j=3
k=6k=6
15 10 22
2215
28
116
1410
mergeArrays
3 5 30 6 14 50a:a: b:b:
3 5 6tmp:tmp:
i=3i=3 j=4j=4
k=7k=7
15 10 22
2815
28 43
22
117
1410
mergeArrays
3 5 6 14 50a:a: b:b:
3 5 6tmp:tmp:
i=4i=4 j=4j=4
k=8k=8
15 10 22
3015
28 43
22
30
28
118
1410
mergeArrays
3 5 6 14 50a:a: b:b:
3 5 6 30tmp:tmp:
i=5i=5 j=4j=4
k=9k=9
15 10 22
15
28 43
22
30
28 43 50
Done.
119
Merge Sort and Linked Lists
Sort Sort
Merge
120
Mergesort AnalysisMerging 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
121
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
122
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
123
Quicksort
First the list is partitioned around a pivot value. Pivot can be chosen from the beginning, end or middle of list):
8 32 11 754 10124 5
5
pivot value
124
Quicksort
The pivot is swapped to the last position and the remaining elements are compared starting at theends.
8 3 2 11 7 54 10124 5
low high
5
pivot value
125
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 510124 6
low high
5
pivot value
312
126
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 54 10124 6
low high
5
pivot value
3 2
127
Quicksort
Then the two values are swapped and the index values are updated:
8 6 2 11 7 54 10124 6
low high
5
pivot value
32 12
128
Quicksort
This continues until the two index values pass each other:
8 6 12 11 7 5424 6
low high
5
pivot value
3103 10
129
Quicksort
This continues until the two index values pass each other:
8 6 12 11 7 5424 6
lowhigh
5
pivot value
103
130
Quicksort
Then the pivot value is swapped into position:
8 6 12 11 7 5424 6
lowhigh
103 85
131
Quicksort
Recursively quicksort the two parts:
5 6 12 11 7 8424 6103
Quicksort the left part Quicksort the right part
5
132
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
133
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