searching and sorting organized

This commit is contained in:
Mari Wahl 2015-01-07 12:40:24 -05:00
parent 91825867f6
commit 28b84cef65
23 changed files with 193 additions and 471 deletions

View File

@ -1,56 +0,0 @@
#!/usr/bin/env python
__author__ = "bt3"
def binary_search_rec(array, item, lo=0, hi = None):
'''
>>> binary_search_rec([2,3,5,6,8,10,15,23], 15)
(True, 6)
>>> binary_search_rec([2,3,5,6,8,10,15,23], 4)
False
'''
hi = hi or len(array)
if hi < lo :
return False
mid = (hi + lo)//2
if array[mid] == item:
return True, mid
elif array[mid] < item:
return binary_search_rec(array, item, mid + 1, hi)
else:
return binary_search_rec(array[:mid], item, lo, mid -1)
def binary_search_iter(array, item):
'''
>>> binary_search_iter([2,3,5,6,8,10,15,23], 15)
(True, 6)
>>> binary_search_iter([2,3,5,6,8,10,15,23], 4)
False
'''
hi = len(array)
lo = 0
while lo < hi:
mid = (hi+lo)//2
if array[mid] == item:
return True, mid
elif array[mid] > item:
hi = mid
else:
lo = mid + 1
return False
if __name__ == '__main__':
import doctest
doctest.testmod()

View File

@ -1,27 +0,0 @@
#!/usr/bin/env python
__author__ = "bt3"
def qs(array):
'''
>>> qs([4,1,6,2,7,9,3])
[1, 2, 3, 4, 6, 7, 9]
'''
if len(array) < 2:
return array
piv = len(array)//2
piv_element = array[piv]
new_array = array[:piv] + array[piv+1:]
left = [a for a in new_array if a <= piv_element]
right = [a for a in new_array if a > piv_element]
return qs(left) + [array[piv]] + qs(right)
if __name__ == '__main__':
import doctest
doctest.testmod()

View File

@ -1,49 +1,56 @@
#!/usr/bin/python #!/usr/bin/env python
__author__ = "Mari Wahl" __author__ = "bt3"
__email__ = "marina.w4hl@gmail.com"
def binary_search(seq, key): def binary_search_rec(array, item, lo=0, hi = None):
''' binary search iterative algorithm ''' '''
''' observe that the index is returned ''' >>> binary_search_rec([2,3,5,6,8,10,15,23], 15)
hi = len(seq) (True, 6)
>>> binary_search_rec([2,3,5,6,8,10,15,23], 4)
False
'''
hi = hi or len(array)
if hi < lo :
return False
mid = (hi + lo)//2
if array[mid] == item:
return True, mid
elif array[mid] < item:
return binary_search_rec(array, item, mid + 1, hi)
else:
return binary_search_rec(array[:mid], item, lo, mid -1)
def binary_search_iter(array, item):
'''
>>> binary_search_iter([2,3,5,6,8,10,15,23], 15)
(True, 6)
>>> binary_search_iter([2,3,5,6,8,10,15,23], 4)
False
'''
hi = len(array)
lo = 0 lo = 0
while lo < hi: while lo < hi:
mid = (hi+lo)//2 mid = (hi+lo)//2
if seq[mid] == key: if array[mid] == item:
return mid return True, mid
elif key < seq[mid]: elif array[mid] > item:
hi = mid hi = mid
else: else:
lo = mid + 1 lo = mid + 1
return False
def binary_search_rec(seq, key, lo=0, hi=None):
''' binary search recursive algorithm '''
hi = hi or len(seq)
if hi < lo: return None
mid = (hi + lo) // 2
if seq[mid] == key:
return mid
elif seq[mid] < key:
return binary_search_rec(seq, key, mid + 1, hi)
else:
return binary_search_rec(seq, key, lo, mid - 1)
def test_binary_search():
seq = [1,2,5,6,7,10,12,12,14,15]
key = 6
assert(binary_search(seq, key) == 3)
assert(binary_search_rec(seq, key) == 3)
print('Tests passed!')
if __name__ == '__main__':
test_binary_search()
if __name__ == '__main__':
import doctest
doctest.testmod()

View File

@ -1,75 +1,89 @@
#!/usr/bin/python #!/usr/bin/env python
__author__ = "Mari Wahl" __author__ = "bt3"
__email__ = "marina.w4hl@gmail.com"
''' Searches an element in a matrix where in every row, the values are increasing from left to right, but the last number in a row is smaller than the first number in the next row. def binary_search_matrix_rec(m, key, lo=0, hi=None):
'''
(1) The naive brute force solution (sequential search) scan all numbers and cost O(nm). However, since the numbers are already sorted, the matrix can be viewed as a 1D sorted array. The binary search algorithm is suitable. The efficiency is O(logmn).
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> binary_search_matrix_rec(m, 6) >>> binary_search_matrix_rec(m, 6)
(1, 2) (1, 2)
>>> binary_search_matrix_rec(m, 12) >>> binary_search_matrix_rec(m, 12)
>>> binary_search_matrix_iter(m, 6)
(1, 2)
>>> binary_search_matrix_iter(m, 12)
>>> binary_search_matrix_iter(m, 1)
(0, 0)
(2) Another solution is "discarding" arrays in the way. The efficiency is O(logm).
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> searching_matrix(m, 6)
(1, 2)
>>> searching_matrix(m, 12)
''' '''
if not m:
return None
def binary_search_matrix_rec(m, key, lo=0, hi=None):
if not m: return None
rows = len(m) rows = len(m)
cols = len(m[0]) cols = len(m[0])
hi = hi or rows*cols hi = hi or rows*cols
if hi > lo: # -----> REMEMBER THIS OR INDEX WILL EXPLODE!!!!!!!!
if hi > lo:
mid = (hi + lo)//2 mid = (hi + lo)//2
row = mid//cols row = mid//cols
col = mid%cols col = mid%cols
item = m[row][col] item = m[row][col]
if key == item: return row, col
elif key < item: return binary_search_matrix_rec(m, key, lo, mid-1) if key == item:
else: return binary_search_matrix_rec(m, key, mid+1, hi) return row, col
elif key < item:
return binary_search_matrix_rec(m, key, lo, mid-1)
else:
return binary_search_matrix_rec(m, key, mid+1, hi)
return None return None
def binary_search_matrix_iter(m, key): def binary_search_matrix_iter(m, key):
if not m: return None '''
'''
if not m:
return None
rows = len(m) rows = len(m)
cols = len(m[0]) cols = len(m[0])
lo, hi = 0, rows*cols lo, hi = 0, rows*cols
while lo < hi: while lo < hi:
mid = (hi + lo)//2 mid = (hi + lo)//2
row = mid//rows row = mid//rows
col = mid%rows col = mid%rows
item = m[row][col] item = m[row][col]
if key == item: return (row, col) if key == item:
elif key < item: hi = mid return (row, col)
else: lo = mid +1 elif key < item:
hi = mid
else:
lo = mid +1
return None return None
def searching_matrix(m, key): def searching_matrix(m, key):
if not m: return None '''
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> searching_matrix(m, 6)
(1, 2)
>>> searching_matrix(m, 12)
'''
if not m:
return None
rows = len(m) rows = len(m)
cols = len(m[0]) cols = len(m[0])
i, j = 0, cols -1 i, j = 0, cols -1
while i < rows and j > 0: while i < rows and j > 0:
item = m[i][j] item = m[i][j]
if key == item: return (i, j) if key == item:
elif key < item: j -= 1 return (i, j)
else: i += 1 elif key < item:
j -= 1
else:
i += 1
return None return None

View File

@ -1,21 +1,27 @@
#!/usr/bin/python #!/usr/bin/env python
__author__ = "Mari Wahl" __author__ = "bt3"
__email__ = "marina.w4hl@gmail.com"
''' Given a sorted array that was rotated, find an item with binary search: '''
Given a sorted array that was rotated, find an item with binary search:
''' '''
def find_element_rot_array(seq, key, lo=0, hi=None): def find_element_rot_array(seq, key, lo=0, hi=None):
hi = hi or len(seq) hi = hi or len(seq)
if hi <= lo: return None # base case: <= for odd and even numbers! if hi <= lo:
return None # base case: <= for odd and even numbers!
mid = (hi + lo) // 2 mid = (hi + lo) // 2
if key == seq[mid]: return mid
if key == seq[mid]:
return mid
# if left is ordered --> we work here # if left is ordered --> we work here
if seq[lo] <= seq[mid]: if seq[lo] <= seq[mid]:
# now, is the key there? # now, is the key there?
if key < seq[mid] and key >= seq[lo]: if key < seq[mid] and key >= seq[lo]:
return find_element_rot_array(seq, key, lo, mid) return find_element_rot_array(seq, key, lo, mid)
@ -25,6 +31,7 @@ def find_element_rot_array(seq, key, lo=0, hi=None):
# right is ordered --> we work here # right is ordered --> we work here
else: else:
# now, is the key there? # now, is the key there?
if key > seq[mid] and key <= seq[hi-1]: # stupid hi-1!!! if key > seq[mid] and key <= seq[hi-1]: # stupid hi-1!!!
return find_element_rot_array(seq, key, mid+1, hi) return find_element_rot_array(seq, key, mid+1, hi)

View File

@ -1,15 +1,15 @@
#!/usr/bin/python #!/usr/bin/env python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
__author__ = "bt3"
def find_max_unimodal_array(A): def find_max_unimodal_array(A):
if len(A) <= 2 : return None if len(A) <= 2 :
return None
left = 0 left = 0
right = len(A)-1 right = len(A)-1
while right > left +1: while right > left +1:
mid = (left + right)//2 mid = (left + right)//2
if A[mid] > A[mid-1] and A[mid] > A[mid+1]: if A[mid] > A[mid-1] and A[mid] > A[mid+1]:
return A[mid] return A[mid]
@ -17,6 +17,7 @@ def find_max_unimodal_array(A):
left = mid left = mid
else: else:
right = mid right = mid
return None return None

View File

@ -1,14 +1,11 @@
#!/usr/bin/python #!/usr/bin/env python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
__author__ = "bt3"
''' implement square root using binary search '''
def find_sqrt_bin_search(n, error=0.001): def find_sqrt_bin_search(n, error=0.001):
''' implement square root using binary search '''
lower = n < 1 and n or 1 lower = n < 1 and n or 1
upper = n < 1 and 1 or n upper = n < 1 and 1 or n
mid = lower + (upper - lower) / 2.0 mid = lower + (upper - lower) / 2.0

View File

@ -1,20 +1,22 @@
#!/usr/bin/python #!/usr/bin/env python
__author__ = "Mari Wahl" __author__ = "bt3"
__email__ = "marina.w4hl@gmail.com"
''' Given a sorted an array with empty strings, we use binary search to find some string (since ''' Given a sorted an array with empty strings,
the list is sorted): we use binary search to find some string (since the list is sorted):
--> we deal with the empty strings with strip and then run to left and right, or move --> we deal with the empty strings with strip and then run to left
mid to the closed non-empty str (remember that the index must be conserved): and right, or move mid to the closed non-empty str (remember that
the index must be conserved):
''' '''
def find_str_array_with_empty_str(seq, s1): def find_str_array_with_empty_str(seq, s1):
if not seq or not s1: return None if not seq or not s1:
return None
hi = len(seq) hi = len(seq)
lo = 0 lo = 0
while hi > lo: while hi > lo:
mid = (hi+lo)//2 mid = (hi+lo)//2
@ -32,9 +34,12 @@ def find_str_array_with_empty_str(seq, s1):
right += 1 right += 1
left -= 1 left -= 1
if s1 == seq[mid] == s1: return mid if s1 == seq[mid] == s1:
elif s1 < seq[mid]: hi = mid return mid
else: lo = mid + 1 elif s1 < seq[mid]:
hi = mid
else:
lo = mid + 1

View File

@ -1,8 +1,6 @@
#!/usr/bin/python #!/usr/bin/env python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
__author__ = "bt3"
def binary_serch_counting(lst1, k, lo=0, hi=None): def binary_serch_counting(lst1, k, lo=0, hi=None):
if hi is None: hi = len(lst1) if hi is None: hi = len(lst1)
@ -19,10 +17,12 @@ def binary_serch_counting(lst1, k, lo=0, hi=None):
def find_time_occurrence_list(seq, k): def find_time_occurrence_list(seq, k):
""" find how many times a k element appears in a sorted list. One way of doing this is using """ find how many times a k element appears in a sorted list.
collections.OrderedDict to no mess with the sorting, and add entries for every count. This One way of doing this is using collections.OrderedDict to no
should be O(n). It has a O(1) space complexity since the size of the dict is fixed. mess with the sorting, and add entries for every count. This
Another way, since the array is sorted, it to use binary search, since this is only O(logn). should be O(n). It has a O(1) space complexity since the size of
the dict is fixed. Another way, since the array is sorted, it to
use binary search, since this is only O(logn).
""" """
index_some_k = binary_serch_counting(seq, k) index_some_k = binary_serch_counting(seq, k)
count = 1 count = 1

View File

@ -1,80 +0,0 @@
#!/usr/bin/python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' using sets '''
def intersection_two_arrays_sets(seq1, seq2):
''' find the intersection of two arrays using set proprieties '''
set1 = set(seq1)
set2 = set(seq2)
return set1.intersection(set2) #same as list(set1 & set2
''' using merge sort '''
def intersection_two_arrays_ms(seq1, seq2):
''' find the intersection of two arrays using merge sort '''
res = []
while seq1 and seq2:
if seq1[-1] == seq2[-1]:
res.append(seq1.pop())
seq2.pop()
elif seq1[-1] > seq2[-1]:
seq1.pop()
else:
seq2.pop()
res.reverse()
return res
''' using binary search '''
def binary_search(seq, key, lo=0, hi=None):
''' binary search iterative algorithm '''
hi = hi or len(seq)
while lo < hi:
mid = (hi+lo) // 2
if seq[mid] == key:
return True
elif key > seq[mid]:
lo = mid + 1
else:
hi = mid
return None
def intersection_two_arrays_bs(seq1, seq2):
''' if A small and B is too large, we can do a binary search on each entry in B '''
''' only works if sorted and the small sequence has not larger nmbers!!!'''
if len(seq1) > len(seq2): seq, key = seq1, seq2
else: seq, key = seq2, seq1
intersec = []
for item in key:
if binary_search(seq, item):
intersec.append(item)
return intersec
def test_intersection_two_arrays(module_name='this module'):
seq1 = [1,2,3,5,7,8]
seq2 = [3,5,6]
assert(set(intersection_two_arrays_sets(seq1,seq2)) == set([3,5]))
assert(intersection_two_arrays_bs(seq1,seq2) == [3,5])
assert(intersection_two_arrays_ms(seq1,seq2) == [3,5])
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_intersection_two_arrays()

View File

@ -1,8 +1,6 @@
#!/usr/bin/python #!/usr/bin/env python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
__author__ = "bt3"

View File

@ -1,12 +1,10 @@
#!/usr/bin/env python
#!/usr/bin/python __author__ = "bt3"
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
import random import random
''' The simplest way...''' ''' The simplest way...'''
def quickSelect(seq, k): def quickSelect(seq, k):
# this part is the same as quick sort # this part is the same as quick sort

View File

@ -1,8 +1,6 @@
#!/usr/bin/python #!/usr/bin/env python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
__author__ = "bt3"
import numpy import numpy

View File

@ -1,8 +1,6 @@
#!/usr/bin/python #!/usr/bin/env python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
__author__ = "bt3"
def sequential_search(seq, n): def sequential_search(seq, n):

View File

@ -7,8 +7,6 @@ def bubble_sort(seq):
""" """
Implementation of bubble sort. Implementation of bubble sort.
O(n2) and thus highly ineffective. O(n2) and thus highly ineffective.
:param seq: the sequence to be sorted.
:return: the sorted sequence.
""" """
size = len(seq) -1 size = len(seq) -1
for num in range(size, 0, -1): for num in range(size, 0, -1):
@ -24,9 +22,6 @@ def test_bubble_sort(module_name='this module'):
seq = [4, 5, 2, 1, 6, 2, 7, 10, 13, 8] seq = [4, 5, 2, 1, 6, 2, 7, 10, 13, 8]
assert(bubble_sort(seq) == sorted(seq)) assert(bubble_sort(seq) == sorted(seq))
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__': if __name__ == '__main__':
test_bubble_sort() test_bubble_sort()

View File

@ -19,7 +19,6 @@ def count_sort_dict(a):
def test_count_sort(): def test_count_sort():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3] seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3]
assert(count_sort_dict(seq) == sorted(seq)) assert(count_sort_dict(seq) == sorted(seq))
print('Tests passed!')
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -18,7 +18,6 @@ def gnome_sort(seq):
def test_gnome_sort(): def test_gnome_sort():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3] seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3]
assert(gnome_sort(seq) == sorted(seq)) assert(gnome_sort(seq) == sorted(seq))
print('Tests passed!')
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -31,7 +31,6 @@ def test_insertion_sort():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3] seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3]
assert(insertion_sort(seq) == sorted(seq)) assert(insertion_sort(seq) == sorted(seq))
assert(insertion_sort_rec(seq) == sorted(seq)) assert(insertion_sort_rec(seq) == sorted(seq))
print('Tests passed!')
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -2,7 +2,6 @@
__author__ = "bt3" __author__ = "bt3"
''' '''
You have two arrays with N integers in them. Merge those arrays using a You have two arrays with N integers in them. Merge those arrays using a
recursive algorithm so that the integers in the final array are sorted. recursive algorithm so that the integers in the final array are sorted.

View File

@ -3,56 +3,12 @@
__author__ = "bt3" __author__ = "bt3"
''' Some examples of how to implement Merge Sort in Python.
--> RUNTIME: WORST/BEST/AVERAGE Is O(nlogn)
--> space complexity is O(n) for arrays
--> in general not in place, good for large arrays
--> In the case of two arrays: we can merge two arrays using the merge function from the merge sort
--> we can do this for files too, merging each two
1) If we can modify the arrays (pop) we can use:
def merge(left, right):
if not left or not right: return left or right # nothing to be merged
result = []
while left and right:
if left[-1] >= right[-1]:
result.append(left.pop())
else:
result.append(right.pop())
result.reverse()
return (left or right) + result
2) If we can't modify or we want to in place, we need two pointers:
>>> l1 = [1, 2, 3, 4, 5, 6, 7]
>>> l2 = [2, 4, 5, 8]
>>> merge(l1, l2)
[1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 8]
3) For example, in the case we have a big array filled 0s in the end, and another array with the size of the number of 0s:
>>> l1 = [1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0]
>>> l2 = [2, 4, 5, 8]
>>> merge_two_arrays_inplace(l1, l2)
[1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 8]
4) If we want to merge sorted files (and we have plenty of RAM to load all files):
>>> list_files = ['1.dat', '2.dat', '3.dat']
>>> merge_files(list_files)
[1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8]
'''
"""
The typical example...
"""
def merge_sort(seq): def merge_sort(seq):
'''
>>> seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
>>> merge_sort(seq)
[0, 1, 2, 2, 3, 3, 5, 5, 6, 6, 8]
'''
if len(seq) < 2: if len(seq) < 2:
return seq return seq
mid = len(seq)//2 mid = len(seq)//2
@ -73,22 +29,21 @@ def merge_sort(seq):
# separating the merge part in another function
'''
We could also divide this sort into two parts, separating
the merge part in another function
'''
def merge_sort_sep(seq): def merge_sort_sep(seq):
'''
>>> seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
>>> merge_sort_sep(seq)
[0, 1, 2, 2, 3, 3, 5, 5, 6, 6, 8]
'''
if len(seq) < 2 : if len(seq) < 2 :
return seq # base case return seq
mid = len(seq)//2 mid = len(seq)//2
left = merge_sort(seq[:mid]) left = merge_sort(seq[:mid])
right = merge_sort(seq[mid:]) # notice that mid is included! right = merge_sort(seq[mid:]) # notice that mid is included!
return merge(left, right) # merge iteratively return merge(left, right) # merge iteratively
def merge(left, right): def merge(left, right):
if not left or not right: if not left or not right:
return left or right # nothing to be merged return left or right # nothing to be merged
@ -106,43 +61,6 @@ def merge(left, right):
return result return result
''' The following merge functions is O(2n) and
illustrate many features in Python that '''
def merge_2n(left, right):
if not left or not right: return left or right # nothing to be merged
result = []
while left and right:
if left[-1] >= right[-1]:
result.append(left.pop())
else:
result.append(right.pop())
result.reverse()
return (left or right) + result
''' Merge two arrays in place '''
def merge_two_arrays_inplace(l1, l2):
if not l1 or not l2: return l1 or l2 # nothing to be merged
p2 = len(l2) - 1
p1 = len(l1) - len(l2) - 1
p12 = len(l1) - 1
while p2 >= 0 and p1 >= 0:
item_to_be_merged = l2[p2]
item_bigger_array = l1[p1]
if item_to_be_merged < item_bigger_array:
l1[p12] = item_bigger_array
p1 -= 1
else:
l1[p12] = item_to_be_merged
p2 -= 1
p12 -= 1
return l1
''' Merge sort for files ''' ''' Merge sort for files '''
def merge_files(list_files): def merge_files(list_files):
result = [] result = []
@ -159,16 +77,6 @@ def merge_files(list_files):
return final return final
def test_merge_sort():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
seq_sorted = sorted(seq)
assert(merge_sort(seq) == seq_sorted)
assert(merge_sort_sep(seq) == seq_sorted)
print('Tests passed!')
if __name__ == '__main__': if __name__ == '__main__':
test_merge_sort() import doctest
doctest.testmod()

View File

@ -3,38 +3,23 @@
__author__ = "bt3" __author__ = "bt3"
''' Some examples of how to implement Quick Sort in Python def qs(array):
--> RUNTIME: BEST/AVERAGE Is O(nlogn), WORST is O(n2)
--> the first example is not in place, the second is in place
--> test with two element arrays, identical values
Quick sort in place:
1) select pivot as the index = 0
2) start pointer1 at index = 1 and pointer2 in the last element
3) while pointer1 < pointer2:
if value in pointer1 <= pivot
swap value in pointer1 with value in pointer2 and advanced pointer2
else
advance pointer1
4) now the array is like this:
[pivot, larger than pivot, smaller than pivot]
5) swap the pivot where pointer 1 stop
6) do recursively for [smaller] + [pivot] + [larger]
''' '''
>>> qs([4,1,6,2,7,9,3])
[1, 2, 3, 4, 6, 7, 9]
'''
if len(array) < 2:
return array
piv = len(array)//2
piv_element = array[piv]
new_array = array[:piv] + array[piv+1:]
left = [a for a in new_array if a <= piv_element]
right = [a for a in new_array if a > piv_element]
return qs(left) + [array[piv]] + qs(right)
def quick_sort(seq):
if len(seq) < 2 : return seq
mid = len(seq)//2
pi = seq[mid]
seq = seq[:mid] + seq[mid+1:]
left = quick_sort([x for x in seq if x <= pi]) # REMEMBER TO INCLUDE X (OR IN RIGHT)
right = quick_sort([x for x in seq if x > pi])
return left + [pi] + right
""" we can also divide them into two functions """ """ we can also divide them into two functions """
@ -45,39 +30,20 @@ def partition(seq):
return lo, pi, hi return lo, pi, hi
def quick_sort_divided(seq): def quick_sort_divided(seq):
if len(seq) < 2: return seq '''
>>> quick_sort_divided([4,1,6,2,7,9,3])
[1, 2, 3, 4, 6, 7, 9]
'''
if len(seq) < 2:
return seq
lo, pi, hi = partition(seq) lo, pi, hi = partition(seq)
return quick_sort_divided(lo) + [pi] + quick_sort_divided(hi) return quick_sort_divided(lo) + [pi] + quick_sort_divided(hi)
''' quick_sort in place '''
def quick_sort_in(seq):
if len(seq) < 2 : return seq
if len(seq) == 2 and seq[0] > seq[1]:
seq[0], seq[1] = seq[1], seq[0] # problems when only 2 elements because of swap
pivot = seq[0] # start at the ends because we don't know how many elements
p1, p2 = 1, len(seq) -1 # set pointers at both ends
while p1 < p2: # must be < or out of range
if seq[p1] <= pivot: # must be <= because of pivot swap
seq[p1], seq[p2] = seq[p2], seq[p1]
p2 -= 1
else:
p1 += 1
seq[0], seq[p1] = seq[p1], pivot
return quick_sort_in(seq[p1+1:]) + [seq[p1]] + quick_sort_in(seq[:p1])
def test_quick_sort():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
assert(quick_sort(seq) == sorted(seq))
assert(quick_sort_divided(seq) == sorted(seq))
print('Tests passed!')
if __name__ == '__main__': if __name__ == '__main__':
test_quick_sort() import doctest
doctest.testmod()

View File

@ -17,7 +17,6 @@ def selection_sort(seq):
def test_selection_sort(): def test_selection_sort():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
assert(selection_sort(seq) == sorted(seq)) assert(selection_sort(seq) == sorted(seq))
print('Tests passed!')
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -3,33 +3,31 @@
__author__ = "bt3" __author__ = "bt3"
''' A method to sort an array so that all the anagrams are together. Since we only ''' A method to sort an array so that all the anagrams are together.
want the anagrams to be grouped, we can use a dictionary for this task. This Since we only want the anagrams to be grouped, we can use a
algorithm is O(n). dictionary for this task. This algorithm is O(n).
>>> l1 = ['hat', 'ball', 'tha', 'cut', 'labl', 'hta', 'cool', 'cuy', 'uct']
>>> sort_anagrams_together(l1)
['cut', 'uct', 'cool', 'ball', 'labl', 'hat', 'tha', 'hta', 'cuy']
''' '''
from collections import defaultdict from collections import defaultdict
def sort_anagrams_together(l1): def sort_anagrams_together(l1):
'''
>>> l1 = ['hat', 'ball', 'tha', 'cut', 'labl', 'hta', 'cool', 'cuy', 'uct']
>>> sort_anagrams_together(l1)
['cuy', 'cut', 'uct', 'cool', 'ball', 'labl', 'hat', 'tha', 'hta']
'''
result = [] result = []
# step 1 save the anagrams together dict_aux = defaultdict(list)
dict_aux = defaultdict(list) # rememebr to indicate the type
for word in l1: for word in l1:
key = ''.join(sorted(word)) # need to sort the strings and join it key = ''.join(sorted(word))
dict_aux[key].append(word) # because only sorted give a list of each char dict_aux[key].append(word)
# step 2 print the anagrams. Note that if you want everything
# sorted you would have to sort the keys and insert the angrams after that
for key in dict_aux: for key in dict_aux:
result.extend(dict_aux[key]) result.extend(dict_aux[key])
return result return result
if __name__ == '__main__': if __name__ == '__main__':
import doctest import doctest
doctest.testmod() doctest.testmod()