def partition(numbers, pivot): '''The original partition scheme described by C.A.R. Hoare uses two indices that start at the ends of the array being partitioned, then move toward each other, until they detect an inversion: a pair of elements, one greater than or equal to the pivot, one lesser or equal, that are in the wrong order relative to each other. The inverted elements are then swapped''' left = DoubleLinkedList() right = DoubleLinkedList() numbers.detach_node(pivot) i = numbers.begin j = numbers.end while True: while i.value <= pivot.value: if i == numbers.end: break i = i.next while j.value >= pivot.value: if j == numbers.begin: break j = j.prev #Trying to avoid having to tack on index numbers to my #double linked lists. Using a "position()" function to #calculate the position instead if sorting.position(numbers, i) < sorting.position(numbers, j): i.value, j.value = j.value, i.value else: if i.value > pivot.value: split = sorting.position(numbers, i) - 1 else: split = sorting.position(numbers, i) while numbers.count() > 0: if split > 0: #print("split=",split,"num=",numbers.begin) left.push(numbers.unshift()) split -= 1 else: #print("split=",split,"num=",numbers.begin) right.push(numbers.unshift()) break return left, right
def merge(left, right): ''' function merge(left, right) var result := empty list while left is not empty and right is not empty do if first(left) <= first(right) then append first(left) to result left := rest(left) else append first(right) to result right := rest(right) while left is not empty do append first(left) to result left := rest(left) while right is not empty do append first(right) to result right := rest(right) return result ''' result = DoubleLinkedList() while left.count() > 0 and right.count() > 0: if left.begin.value <= right.begin.value: result.push(left.unshift()) else: result.push(right.unshift()) while left.count() > 0: result.push(left.unshift()) while right.count() > 0: result.push(right.unshift()) return result
def quick_sort(numbers): if numbers.count() <= 1: return numbers result = DoubleLinkedList() #There are many different strategies for picking a pivot #This allows for flexibility in defining the pivot pivotIndex = randint(1, numbers.count()) index = 1 pivot = numbers.begin while index != pivotIndex: pivot = pivot.next index += 1 #Now send the list to partition() and get back two lists, #one that contains values less than, and one that has #values greater than the pivot left, right = sorting.partition(numbers, pivot) #Prepend the sorted left side to the pivot and append the #sorted right side sorting.quick_sort(left) while left.count() > 0: result.push(left.unshift()) result.push(pivot) sorting.quick_sort(right) while right.count() > 0: result.push(right.unshift()) return result
def homogenous_list(): numbers = DoubleLinkedList() numbers.push(1) numbers.push(1) numbers.push(1) numbers.push(1) numbers.push(1) return numbers
def presorted_list(): numbers = DoubleLinkedList() numbers.push(1) numbers.push(2) numbers.push(3) numbers.push(4) numbers.push(5) return numbers
def merge_sort(numbers): ''' Pseudocode from wikipedia: function merge_sort(list m) if length of m <= 1 then return m var left := empty list var right := empty list for each x with index i in m do if i < (length of m)/2 then add x to left else add x to right left := merge_sort(left) right := merge_sort(right) return merge(left, right) ''' if numbers.count() <= 1: return numbers left = DoubleLinkedList() right = DoubleLinkedList() split = numbers.count() / 2 while numbers.count() > 0: if split > 0: left.push(numbers.unshift()) split -= 1 else: right.push(numbers.unshift()) left = sorting.merge_sort(left) right = sorting.merge_sort(right) return sorting.merge(left, right)
class Dictionary(object): ''' Transcription of Zed's prototype dictionary class Terms: bucket = a list within the Map list that contains key value pairs slot = a key value pair within a bucket node = any generic node within a DoubleLinkedList ''' def __init__(self, num_buckets=256): '''Initialize a map with num_buckets number of buckets. Basically a list of lists''' self.map = DoubleLinkedList() for i in range(0, num_buckets): self.map.push(DoubleLinkedList()) def hash_key(self, key): '''Take a key and create a number, then convert it to an index for the Map's buckets. Basically creates a randomized index for each key''' return hash(key) % self.map.count() def get_bucket(self, key): '''Given a key, find the bucket where it lives''' bucket_id = self.hash_key(key) print("get_bucket() calling get() on", self.map, "with", bucket_id) return self.map.get(bucket_id) def get_slot(self, key, default=None): '''return the bucket and node (key,value) for a given key Hmmm, the 'default' parameter never gets used''' print("get_slot() calling get_bucket() with", self, key) bucket = self.get_bucket(key) if bucket: node = bucket.begin #Not sure why an index is needed, since it's never #used later i = 0 while node: if key == node.value[0]: return bucket, node else: node = node.next i += 1 return bucket, None def get(self, key, default=None): '''Take a key and get the its full slot and value, or the default Hmmmm, Zed's code ends with "or node" which doesn't make sense to me. Changed to "or default"''' print("get() calling get_slot() with", self, key) bucket, node = self.get_slot(key, default=default) return node and node.value[1] or default def set(self, key, value): '''Set a key to the given value, replacing any old values''' bucket, slot = self.get_slot(key) if slot: '''key already exists, replace it''' '''Why does Zed use python builtin lists here, rather than the DoubleLinkedLists we've been using?''' slot.value = (key, value) else: bucket.push((key, value)) def delete(self, key): '''Deletes a given key from the map''' bucket = self.get_bucket(key) node = bucket.begin while node: k, v = node.value if key == k: bucket.detach_node(node) break def list(self): '''Prints out the map''' bucket_node = self.map.begin while bucket_node: slot_node = bucket_node.value.begin while slot_node: print(slot_node.value) slot_node = slot_node.next bucket_node = bucket_node.next
def homogenous_list(count): numbers = DoubleLinkedList() for i in range(1, count + 1): numbers.push(1) return numbers
def presorted_list(count): numbers = DoubleLinkedList() for i in range(1, count + 1): numbers.push(i) return numbers