Skip to content

Commit 5e2920b

Browse files
committed
source code for chapter 12
1 parent 767a9a5 commit 5e2920b

File tree

8 files changed

+325
-0
lines changed

8 files changed

+325
-0
lines changed

ch12/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__all__ = ['decorated_merge_sort', 'merge_array', 'merge_nonrecur', 'merge_queue', 'quick_inplace', 'quick_queue', 'quick_select']

ch12/decorated_merge_sort.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright 2013, Michael H. Goldwasser
2+
#
3+
# Developed for use with the book:
4+
#
5+
# Data Structures and Algorithms in Python
6+
# Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
7+
# John Wiley & Sons, 2013
8+
#
9+
# This program is free software: you can redistribute it and/or modify
10+
# it under the terms of the GNU General Public License as published by
11+
# the Free Software Foundation, either version 3 of the License, or
12+
# (at your option) any later version.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+
from .merge_array import merge_sort
23+
24+
class _Item:
25+
"""Lightweight composite to store decorated value for sorting."""
26+
__slots__ = '_key', '_value'
27+
28+
def __init__(self, k, v):
29+
self._key = k
30+
self._value = v
31+
32+
def __lt__(self, other):
33+
return self._key < other._key # compare items based on their keys
34+
35+
def decorated_merge_sort(data, key=None):
36+
"""Demonstration of the decorate-sort-undecorate pattern."""
37+
if key is not None:
38+
for j in range(len(data)):
39+
data[j] = _Item(key(data[j]), data[j]) # decorate each element
40+
merge_sort(data) # sort with existing algorithm
41+
if key is not None:
42+
for j in range(len(data)):
43+
data[j] = data[j]._value # undecorate each element

ch12/merge_array.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Copyright 2013, Michael H. Goldwasser
2+
#
3+
# Developed for use with the book:
4+
#
5+
# Data Structures and Algorithms in Python
6+
# Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
7+
# John Wiley & Sons, 2013
8+
#
9+
# This program is free software: you can redistribute it and/or modify
10+
# it under the terms of the GNU General Public License as published by
11+
# the Free Software Foundation, either version 3 of the License, or
12+
# (at your option) any later version.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+
def merge(S1, S2, S):
23+
"""Merge two sorted Python lists S1 and S2 into properly sized list S."""
24+
i = j = 0
25+
while i + j < len(S):
26+
if j == len(S2) or (i < len(S1) and S1[i] < S2[j]):
27+
S[i+j] = S1[i] # copy ith element of S1 as next item of S
28+
i += 1
29+
else:
30+
S[i+j] = S2[j] # copy jth element of S2 as next item of S
31+
j += 1
32+
33+
def merge_sort(S):
34+
"""Sort the elements of Python list S using the merge-sort algorithm."""
35+
n = len(S)
36+
if n < 2:
37+
return # list is already sorted
38+
# divide
39+
mid = n // 2
40+
S1 = S[0:mid] # copy of first half
41+
S2 = S[mid:n] # copy of second half
42+
# conquer (with recursion)
43+
merge_sort(S1) # sort copy of first half
44+
merge_sort(S2) # sort copy of second half
45+
# merge results
46+
merge(S1, S2, S) # merge sorted halves back into S

ch12/merge_nonrecur.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copyright 2013, Michael H. Goldwasser
2+
#
3+
# Developed for use with the book:
4+
#
5+
# Data Structures and Algorithms in Python
6+
# Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
7+
# John Wiley & Sons, 2013
8+
#
9+
# This program is free software: you can redistribute it and/or modify
10+
# it under the terms of the GNU General Public License as published by
11+
# the Free Software Foundation, either version 3 of the License, or
12+
# (at your option) any later version.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+
import math
23+
24+
def merge(src, result, start, inc):
25+
"""Merge src[start:start+inc] and src[start+inc:start+2*inc] into result."""
26+
end1 = start+inc # boundary for run 1
27+
end2 = min(start+2*inc, len(src)) # boundary for run 2
28+
x, y, z = start, start+inc, start # index into run 1, run 2, result
29+
while x < end1 and y < end2:
30+
if src[x] < src[y]:
31+
result[z] = src[x]
32+
x += 1
33+
else:
34+
result[z] = src[y]
35+
y += 1
36+
z += 1 # increment z to reflect new result
37+
if x < end1:
38+
result[z:end2] = src[x:end1] # copy remainder of run 1 to output
39+
elif y < end2:
40+
result[z:end2] = src[y:end2] # copy remainder of run 2 to output
41+
42+
def merge_sort(S):
43+
"""Sort the elements of Python list S using the merge-sort algorithm."""
44+
n = len(S)
45+
logn = math.ceil(math.log(n,2))
46+
src, dest = S, [None] * n # make temporary storage for dest
47+
for i in (2**k for k in range(logn)): # pass i creates all runs of length 2i
48+
for j in range(0, n, 2*i): # each pass merges two length i runs
49+
merge(src, dest, j, i)
50+
src, dest = dest, src # reverse roles of lists
51+
if S is not src:
52+
S[0:n] = src[0:n] # additional copy to get results to S

ch12/merge_queue.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copyright 2013, Michael H. Goldwasser
2+
#
3+
# Developed for use with the book:
4+
#
5+
# Data Structures and Algorithms in Python
6+
# Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
7+
# John Wiley & Sons, 2013
8+
#
9+
# This program is free software: you can redistribute it and/or modify
10+
# it under the terms of the GNU General Public License as published by
11+
# the Free Software Foundation, either version 3 of the License, or
12+
# (at your option) any later version.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+
from ..ch07.linked_queue import LinkedQueue
23+
24+
def merge(S1, S2, S):
25+
"""Merge two sorted queue instances S1 and S2 into empty queue S."""
26+
while not S1.is_empty() and not S2.is_empty():
27+
if S1.first() < S2.first():
28+
S.enqueue(S1.dequeue())
29+
else:
30+
S.enqueue(S2.dequeue())
31+
while not S1.is_empty(): # move remaining elements of S1 to S
32+
S.enqueue(S1.dequeue())
33+
while not S2.is_empty(): # move remaining elements of S2 to S
34+
S.enqueue(S2.dequeue())
35+
36+
def merge_sort(S):
37+
"""Sort the elements of queue S using the merge-sort algorithm."""
38+
n = len(S)
39+
if n < 2:
40+
return # list is already sorted
41+
# divide
42+
S1 = LinkedQueue() # or any other queue implementation
43+
S2 = LinkedQueue()
44+
while len(S1) < n // 2: # move the first n//2 elements to S1
45+
S1.enqueue(S.dequeue())
46+
while not S.is_empty(): # move the rest to S2
47+
S2.enqueue(S.dequeue())
48+
# conquer (with recursion)
49+
merge_sort(S1) # sort first half
50+
merge_sort(S2) # sort second half
51+
# merge results
52+
merge(S1, S2, S) # merge sorted halves back into S

ch12/quick_inplace.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright 2013, Michael H. Goldwasser
2+
#
3+
# Developed for use with the book:
4+
#
5+
# Data Structures and Algorithms in Python
6+
# Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
7+
# John Wiley & Sons, 2013
8+
#
9+
# This program is free software: you can redistribute it and/or modify
10+
# it under the terms of the GNU General Public License as published by
11+
# the Free Software Foundation, either version 3 of the License, or
12+
# (at your option) any later version.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+
def inplace_quick_sort(S, a, b):
23+
"""Sort the list from S[a] to S[b] inclusive using the quick-sort algorithm."""
24+
if a >= b: return # range is trivially sorted
25+
pivot = S[b] # last element of range is pivot
26+
left = a # will scan rightward
27+
right = b-1 # will scan leftward
28+
while left <= right:
29+
# scan until reaching value equal or larger than pivot (or right marker)
30+
while left <= right and S[left] < pivot:
31+
left += 1
32+
# scan until reaching value equal or smaller than pivot (or left marker)
33+
while left <= right and pivot < S[right]:
34+
right -= 1
35+
if left <= right: # scans did not strictly cross
36+
S[left], S[right] = S[right], S[left] # swap values
37+
left, right = left + 1, right - 1 # shrink range
38+
39+
# put pivot into its final place (currently marked by left index)
40+
S[left], S[b] = S[b], S[left]
41+
# make recursive calls
42+
inplace_quick_sort(S, a, left - 1)
43+
inplace_quick_sort(S, left + 1, b)

ch12/quick_queue.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright 2013, Michael H. Goldwasser
2+
#
3+
# Developed for use with the book:
4+
#
5+
# Data Structures and Algorithms in Python
6+
# Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
7+
# John Wiley & Sons, 2013
8+
#
9+
# This program is free software: you can redistribute it and/or modify
10+
# it under the terms of the GNU General Public License as published by
11+
# the Free Software Foundation, either version 3 of the License, or
12+
# (at your option) any later version.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+
from ..ch07.linked_queue import LinkedQueue
23+
24+
def quick_sort(S):
25+
"""Sort the elements of queue S using the quick-sort algorithm."""
26+
n = len(S)
27+
if n < 2:
28+
return # list is already sorted
29+
# divide
30+
p = S.first() # using first as arbitrary pivot
31+
L = LinkedQueue()
32+
E = LinkedQueue()
33+
G = LinkedQueue()
34+
while not S.is_empty(): # divide S into L, E, and G
35+
if S.first() < p:
36+
L.enqueue(S.dequeue())
37+
elif p < S.first():
38+
G.enqueue(S.dequeue())
39+
else: # S.first() must equal pivot
40+
E.enqueue(S.dequeue())
41+
# conquer (with recursion)
42+
quick_sort(L) # sort elements less than p
43+
quick_sort(G) # sort elements greater than p
44+
# concatenate results
45+
while not L.is_empty():
46+
S.enqueue(L.dequeue())
47+
while not E.is_empty():
48+
S.enqueue(E.dequeue())
49+
while not G.is_empty():
50+
S.enqueue(G.dequeue())

ch12/quick_select.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Copyright 2013, Michael H. Goldwasser
2+
#
3+
# Developed for use with the book:
4+
#
5+
# Data Structures and Algorithms in Python
6+
# Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser
7+
# John Wiley & Sons, 2013
8+
#
9+
# This program is free software: you can redistribute it and/or modify
10+
# it under the terms of the GNU General Public License as published by
11+
# the Free Software Foundation, either version 3 of the License, or
12+
# (at your option) any later version.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+
import random
23+
24+
def quick_select(S, k):
25+
"""Return the kth smallest element of list S, for k from 1 to len(S)."""
26+
if len(S) == 1:
27+
return S[0]
28+
pivot = random.choice(S) # pick random pivot element from S
29+
L = [x for x in S if x < pivot] # elements less than pivot
30+
E = [x for x in S if x == pivot] # elements equal to pivot
31+
G = [x for x in S if pivot < x] # elements greater than pivot
32+
if k <= len(L):
33+
return quick_select(L, k) # kth smallest lies in L
34+
elif k <= len(L) + len(E):
35+
return pivot # kth smallest equal to pivot
36+
else:
37+
j = k - len(L) - len(E) # new selection parameter
38+
return quick_select(G, j) # kth smallest is jth in G

0 commit comments

Comments
 (0)