Beispiel #1
0
        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
Beispiel #2
0
 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
Beispiel #4
0
    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
Beispiel #5
0
    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)
Beispiel #6
0
 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)
Beispiel #7
0
 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
Beispiel #8
0
    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
Beispiel #9
0
    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)