def BSTConverter(lst_to_convert): if len(lst_to_convert) == 0: return None mid = len(lst_to_convert) // 2 node = BSTNode(lst_to_convert[mid]) node.left = BSTConverter(lst_to_convert[:mid]) node.right = BSTConverter(lst_to_convert[mid + 1:]) return node
def recurse(node): # New item is less, go left until spot is found if item < node.data: if node.left == None: node.left = BSTNode(item) else: recurse(node.left) # New item is greater or equal, # go right until spot is found elif node.right == None: node.right = BSTNode(item) else: recurse(node.right)
def build_states(cur_state): """ Builds a tree of states starting from the current game state. Always chooses 2 random move options. (god knows why it's stupid) This method pre-fills the terminal states with scores of 1, -1, and 0. :param cur_state: Game :return: LinkedBST """ states = LinkedBST() st = LinkedStack() states.root = BSTNode([deepcopy(cur_state.board), None, None]) st.push(states.root) while not st.isEmpty(): curr = st.pop() curr_board = curr.data[0] p1w = curr_board.game_over(player=1) p2w = curr_board.game_over(player=2) if p1w: curr.data[1] = 1 continue elif p2w: curr.data[1] = -1 continue cells = curr.data[0].free_cells() if not cells: # No one won and no cells left - it's a tie. curr.data[1] = 0 continue available = random.sample(cells, k=min(len(cells), 2)) for cell in available: new_board = deepcopy(curr.data[0].move( cell, player=1 if curr.data[0].get_turn() % 2 == 1 else 2)) curr.data[0].undo(cell) if curr.left is None: curr.left = BSTNode([new_board, None, cell]) st.add(curr.left) elif curr.right is None: curr.right = BSTNode([new_board, None, cell]) st.add(curr.right) else: break return states
def add(self, item): """Adds item to the tree.""" # Helper function to search for item's position def recurse(node): # New item is less, go left until spot is found if item < node.data: if node.left == None: node.left = BSTNode(item) else: recurse(node.left) # New item is greater or equal, # go right until spot is found elif node.right == None: node.right = BSTNode(item) else: recurse(node.right) # End of recurse # Tree is empty, so new item goes at the root if self.isEmpty(): self._root = BSTNode(item) # Otherwise, search for the item's spot else: recurse(self._root) self._size += 1
def rebalance(self): ''' Rebalances the tree. :return: None ''' def recurse(p, lst): """ make new tree :param p: BSTNode :param lst: list :return: None """ while len(lst) != 0: if len(lst) % 2 == 0: new_lst_1 = lst[0:len(lst) // 2] new_lst_2 = lst[len(lst) // 2:] lst = [] else: new_lst_1 = lst[0:len(lst) // 2 + 1] new_lst_2 = lst[len(lst) // 2 + 1:] lst = [] item1 = new_lst_1.pop(len(new_lst_1) // 2) self._add_left(p, item1) recurse(self.find(item1), new_lst_1) if len(new_lst_2) != 0: item2 = new_lst_2.pop(len(new_lst_2) // 2) self._add_right(p, item2) recurse(self.find(item2), new_lst_2) lst = list(self.inorder()) self.clear() self._root = BSTNode(lst.pop(len(lst) // 2)) recurse(self._root, lst)
def _add_left(self, p, k): """ add left :param p: BSTNode :param k: int or str :return: None """ self._size += 1 p.left = BSTNode(k)
def _add_right(self, p, k): """ add right :param p: BSTNode :param k: int or str :return: None """ p.right = BSTNode(k) self._size += 1
def remove(self, item): """Precondition: item is in self. Raises: KeyError if item is not in self. postcondition: item is removed from self.""" if not item in self: raise KeyError("Item not in tree." "") # Helper function to adjust placement of an item def liftMaxInLeftSubtreeToTop(top): # Replace top's datum with the maximum datum in the left subtree # Pre: top has a left child # Post: the maximum node in top's left subtree # has been removed # Post: top.data = maximum value in top's left subtree parent = top currentNode = top.left while not currentNode.right == None: parent = currentNode currentNode = currentNode.right top.data = currentNode.data if parent == top: top.left = currentNode.left else: parent.right = currentNode.left # Begin main part of the method if self.isEmpty(): return None # Attempt to locate the node containing the item itemRemoved = None preRoot = BSTNode(None) preRoot.left = self._root parent = preRoot direction = 'L' currentNode = self._root while not currentNode == None: if currentNode.data == item: itemRemoved = currentNode.data break parent = currentNode if currentNode.data > item: direction = 'L' currentNode = currentNode.left else: direction = 'R' currentNode = currentNode.right # Return None if the item is absent if itemRemoved == None: return None # The item is present, so remove its node # Case 1: The node has a left and a right child # Replace the node's value with the maximum value in the # left subtree # Delete the maximium node in the left subtree if not currentNode.left == None \ and not currentNode.right == None: liftMaxInLeftSubtreeToTop(currentNode) else: # Case 2: The node has no left child if currentNode.left == None: newChild = currentNode.right # Case 3: The node has no right child else: newChild = currentNode.left # Case 2 & 3: Tie the parent to the new child if direction == 'L': parent.left = newChild else: parent.right = newChild # All cases: Reset the root (if it hasn't changed no harm done) # Decrement the collection's size counter # Return the item self._size -= 1 if self.isEmpty(): self._root = None else: self._root = preRoot.left return itemRemoved
def rebalance(self): ''' Rebalances the tree. return: None ''' new = [] elements = [i for i in self.inorder()] def middle(values): """ values: list with values return: middle value in the values """ return values[int((len(values) - 1) / 2)] def half(values, mid=None): """ Separating the list on two halfs values: list with values mid: the separator return: two lists """ if not mid: mid = middle(values) p1 = [] while values[0] < mid: p1.append(values.pop(0)) return p1, values root = middle(elements) new = [root] ind = elements.index(root) elements.pop(ind) def recurse(values): """ Recursive function to balance the tree values: list with tree values """ if len(values) > 1: half1, half2 = half(values) if half1 and half2: mid1, mid2 = middle(half1), middle(half2) el1, el2 = mid1, mid2 in1, in2 = half1.index(el1), half2.index(el2) new.append(half1.pop(in1)) new.append(half2.pop(in2)) recurse(half1) recurse(half2) elif half1: el1 = middle(half1) in1 = half1.index(el1) new.append(half1.pop(in1)) recurse(half1) elif half2: el1 = middle(half2) in1 = half2.index(el1) new.append(half2.pop(in1)) recurse(half2) elif values: new.append(values[0]) recurse(elements) self._root = BSTNode(new[0]) for i in new[1:]: self.add(i)