diff --git a/names/binary_search_tree.py b/names/binary_search_tree.py new file mode 100644 index 000000000..263aef3f3 --- /dev/null +++ b/names/binary_search_tree.py @@ -0,0 +1,238 @@ +import sys + +from dll_queue import Queue +from dll_stack import Stack +from doubly_linked_list import * + +""" +* Should have the methods `insert`, `contains`, `get_max`. + + * `contains` searches the binary search tree for the input value, returning a boolean indicating whether the value exists in the tree or not. + * `get_max` returns the maximum value in the binary search tree. + * `for_each` performs a traversal of _every_ node in the tree, executing the passed-in callback function on each tree node value. There is a myriad of ways to perform tree traversal; in this case any of them should work. +""" + + +class BinarySearchTree: + def __init__(self, value): # + self.value=value + self.left = None + self.right = None + + + # Adds the input value to the binary search tree, + # adhering to the rules of the ordering of elements in a binary search tree. + #check if there's a new node + + #iterative + def insert(self, value): + new_node = BinarySearchTree(value) + cur_node=self + while True: + if value 0: + if cur_node.left: + queue.append(cur_node.left) + if cur_node.right: + queue.append(cur_node.right) + visited.append(cur_node) + queue.pop(0) + if len(queue)>0: + cur_node=queue[0] + for a in visited: + cb(a.value) + + def for_each_recursive(self,cb): + cb(self.value) + if self.left: + self.left.for_each(cb) + if self.right: + self.right.for_each(cb) + + + + + + # DAY 2 Project -----------------------\ + + + + + # Print all the values in order from low to high + # Hint: Use a recursive, depth first traversal + # call function on root + # if left + # call on left + # if right + # call on right + def in_order_print(self, node): + + if node.left: + node.in_order_print(node.left) + + + print(node.value) + + if node.right: + node.in_order_print(node.right) + + + + + # Print the value of every node, starting with the given node, + # in an iterative breadth first traversal + # make queue + # push root into queue + # while queue not empty + #if left + #add left to back + #if right + #add right to back + def bft_print(self, node): + queue= Queue() + queue.enqueue(node) + while queue.len() > 0: + cur_node=queue.dequeue() + print(cur_node.value) + if cur_node.left: + queue.enqueue(cur_node.left) + if cur_node.right: + queue.enqueue(cur_node.right) + + + + + # Print the value of every node, starting with the given node, + # in an iterative depth first traversal + # make stack + # put the root in the stack + # while stack is not empty + # Pop the top item in the stack + # look right + # push right to the stack + # look left + # if there is a left, push to stack + def dft_print(self, node): + stack= Stack() + stack.push(node) + while stack.len()>0: + cur_node=stack.pop() + print(cur_node.value) + if cur_node.left: + stack.push(cur_node.left) + if cur_node.right: + stack.push(cur_node.right) + + + # STRETCH Goals ------------------------- + # Note: Research may be required + + # Print In-order recursive DFT + def pre_order_dft(self, node): + pass + + # Print Post-order recursive DFT + def post_order_dft(self, node): + pass + + +bst= BinarySearchTree(5) +bst.insert(2) +print(bst.value) + + + + diff --git a/names/dll_queue.py b/names/dll_queue.py new file mode 100644 index 000000000..5fad9a70f --- /dev/null +++ b/names/dll_queue.py @@ -0,0 +1,22 @@ +import sys +sys.path.append('../doubly_linked_list') +from doubly_linked_list import DoublyLinkedList + + + + +class Queue: + def __init__(self): + self.size = 0 + # Why is our DLL a good choice to store our elements? + # self.storage = ? + self.storage=DoublyLinkedList(None) + + def enqueue(self, value): + self.storage.add_to_tail(value) + + def dequeue(self): + return self.storage.remove_from_head() + + def len(self): + return self.storage.length diff --git a/names/dll_stack.py b/names/dll_stack.py new file mode 100644 index 000000000..85ba23c57 --- /dev/null +++ b/names/dll_stack.py @@ -0,0 +1,26 @@ +import sys +sys.path.append('../doubly_linked_list') +from doubly_linked_list import DoublyLinkedList + +class Stack: + def __init__(self, node=None): + # self.head = node + # self.tail = node + # self.length = 1 if node is not None else 0 + self.storage=DoublyLinkedList(None) + + def push(self, value): + # pass + self.storage.add_to_tail(value) + + + def pop(self): + return self.storage.remove_from_tail() + + + + def len(self): + # print(self.storage) + # print(self.storage.length) + return self.storage.length + diff --git a/names/doubly_linked_list.py b/names/doubly_linked_list.py new file mode 100644 index 000000000..fb490c32d --- /dev/null +++ b/names/doubly_linked_list.py @@ -0,0 +1,145 @@ +"""Each ListNode holds a reference to its previous node +as well as its next node in the List.""" + + +class ListNode: + def __init__(self, value, prev=None, next=None): + self.value = value + self.prev = prev + self.next = next + + """Wrap the given value in a ListNode and insert it + after this node. Note that this node could already + have a next node it is point to.""" + def insert_after(self, value): + current_next = self.next + self.next = ListNode(value, self, current_next) + if current_next: + current_next.prev = self.next + + """Wrap the given value in a ListNode and insert it + before this node. Note that this node could already + have a previous node it is point to.""" + def insert_before(self, value): + current_prev = self.prev + self.prev = ListNode(value, current_prev, self) + if current_prev: + current_prev.next = self.prev + + """Rearranges this ListNode's previous and next pointers + accordingly, effectively deleting this ListNode.""" + def delete(self): + if self.prev: + self.prev.next = self.next + if self.next: + self.next.prev = self.prev + + +"""Our doubly-linked list class. It holds references to +the list's head and tail nodes.""" + + +class DoublyLinkedList: + def __init__(self, node=None): + self.head = node + self.tail = node + self.length = 1 if node is not None else 0 + + def __len__(self): + return self.length + + """Wraps the given value in a ListNode and inserts it + as the new head of the list. Don't forget to handle + the old head node's previous pointer accordingly.""" + def add_to_head(self, value): + new_node = ListNode(value, None, None) + self.length += 1 + if not self.head and not self.tail: + self.head = new_node + self.tail = new_node + else: + new_node.next = self.head + self.head.prev = new_node + self.head = new_node + + """Removes the List's current head node, making the + current head's next node the new head of the List. + Returns the value of the removed Node.""" + def remove_from_head(self): + if not self.tail: + return None + value = self.head.value + self.delete(self.head) + return value + + """Wraps the given value in a ListNode and inserts it + as the new tail of the list. Don't forget to handle + the old tail node's next pointer accordingly.""" + def add_to_tail(self, value): + new_node = ListNode(value, None, None) + + if not self.head and not self.tail: + self.head = new_node + self.tail = new_node + else: + new_node.prev = self.tail + self.tail.next = new_node + self.tail = new_node + + self.length += 1 + + """Removes the List's current tail node, making the + current tail's previous node the new tail of the List. + Returns the value of the removed Node.""" + def remove_from_tail(self): + if not self.tail: + return None + else: + value = self.tail.value + self.delete(self.tail) + return value + + """Removes the input node from its current spot in the + List and inserts it as the new head node of the List.""" + def move_to_front(self, node): + if node is self.head: + return + value = node.value + self.delete(node) + self.add_to_head(value) + + """Removes the input node from its current spot in the + List and inserts it as the new tail node of the List.""" + def move_to_end(self, node): + if node is self.tail: + return + value = node[0] + self.delete(node) + self.add_to_tail(value) + + """Removes a node from the list and handles cases where + the node was the head or the tail""" + def delete(self, node): + self.length -= 1 + if self.head is self.tail: + self.head = None + self.tail = None + elif self.head is node: + self.head = node.next + node.delete() + elif self.tail is node: + self.tail = node.prev + node.delete() + else: + node.delete() + + """Returns the highest value currently in the list""" + def get_max(self): + max_value = self.head.value + current = self.head + while current is not None: + if current.value > max_value: + max_value = current.value + current = current.next + + return max_value diff --git a/names/names.py b/names/names.py index 586e8393e..5edfb7077 100644 --- a/names/names.py +++ b/names/names.py @@ -1,4 +1,5 @@ import time +from binary_search_tree import BinarySearchTree start_time = time.time() @@ -11,12 +12,17 @@ f.close() duplicates = [] +bst=BinarySearchTree(names_1[0]) +for name in names_2: + bst.insert(name) + for name_1 in names_1: - for name_2 in names_2: - if name_1 == name_2: + if bst.contains(name_1) is True: duplicates.append(name_1) + end_time = time.time() print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") print (f"runtime: {end_time - start_time} seconds") +#runtime of code is O(n^2) diff --git a/reverse/reverse.py b/reverse/reverse.py index 95ed9d1d4..439e491e2 100644 --- a/reverse/reverse.py +++ b/reverse/reverse.py @@ -43,5 +43,26 @@ def contains(self, value): return False def reverse_list(self): - # TO BE COMPLETED - pass \ No newline at end of file + prev = None + cur = self.head + #accounting for an empty list + if cur: + nxt = cur.get_next() + + #reversing the list + while cur: + cur.set_next(prev) + prev=cur + cur=nxt + if nxt: + nxt=nxt.get_next() + + + self.head=prev + + # print('prev.next.next', prev.next_node.next_node) + + + + + \ No newline at end of file