Ejemplo n.º 1
0
    def test_delete(self):
        items = [10, 5, 15, 3, 8, 7, 9]
        tree = BinarySearchTree()
        for item in items:
            tree.insert(item)

        tree.delete(10)
Ejemplo n.º 2
0
    def test_delete(self):

        ## Delete leaf and root
        bst = BinarySearchTree(['E'])
        bst.delete('E')
        assert bst.items_in_order() == []

        ## Delete left leaf
        bst = BinarySearchTree(['C', 'A', 'B', 'E'])

        bst.delete('B')
        assert bst.items_in_order() == ['A', 'C', 'E']

        ## Delete right leaf
        bst = BinarySearchTree(['A', 'B', 'C', 'E'])

        bst.delete('E')
        assert bst.items_in_order() == ['A', 'B', 'C']

        ## Delete node with only direct child on left
        bst = BinarySearchTree(['C', 'B', 'A', 'E'])

        bst.delete('B')
        assert bst.items_in_order() == ['A', 'C', 'E']

        ## Delete node with only direct child on right
        bst = BinarySearchTree(['C', 'A', 'B', 'E'])

        bst.delete('A')
        assert bst.items_in_order() == ['B', 'C', 'E']
Ejemplo n.º 3
0
 def DISABLED_test_delete_with_3_items(self):
     # Create a complete binary search tree of 3 items in level-order
     items = [2, 1, 3]
     tree = BinarySearchTree(items)
     assert tree.root.data == 2
     assert tree.root.left.data == 1
     assert tree.root.right.data == 3
     # TODO: Test structure of tree after each deletion
     tree.delete(2)
Ejemplo n.º 4
0
class Set:
    """Implements a set using BinarySearchTree"""

    __slots__ = ("data", )

    def __init__(self, it=()):
        self.data = BinarySearchTree(it)

    def add(self, elm):
        self.data.insert(elm)

    def remove(self, elm):
        self.data.delete(elm)

    def union(self, other_set):
        bigger_set = max(self, other_set, key=lambda set: set.size)
        smaller_set = min(self, other_set, key=lambda set: set.size)
        return Set(self.items() + other_set.items())

    def intersection(self, other_set):
        bigger_set = max(self, other_set, key=lambda set: set.size)
        smaller_set = min(self, other_set, key=lambda set: set.size)
        return Set(
            tuple(elm for elm in smaller_set.items()
                  if bigger_set.contains(elm)))

    def difference(self, other_set):
        res = Set()
        for elm in self.items():
            if not other_set.contains(elm):
                res.add(elm)
        return res

    def is_subset(self, other_set):
        for elm in self.items():
            if not other_set.contains(elm):
                return False
        return True

    def items(self):
        return self.data.items_in_order()

    def contains(self, elm):
        return self.data.contains(elm)

    @property
    def size(self):
        return self.data.size

    def __eq__(self, other):
        if isinstance(other, BinarySearchTree):
            return self.data == other
        elif isinstance(other, Set):
            return self.data == other.data
        else:
            raise TypeError("Can only compare with BinarySearchTree and Set")
 def test_delete_ints(self):
     tree = BinarySearchTree([6, 4, 7, 3, 1, 20, 34])
     assert tree.root.data == 6
     assert tree.size == 7
     tree.delete(7)
     assert tree.size == 6
     assert tree.search(7) == None
     assert tree.items_in_order() == [1, 3, 4, 6, 20, 34]
     tree.delete(20)
     assert tree.size == 5
     assert tree.items_in_order() == [1, 3, 4, 6, 34]
Ejemplo n.º 6
0
 def test_delete_with_3_items(self):
     # Create a complete binary search tree of 3 items in level-order
     items = [2, 1, 3]
     tree = BinarySearchTree(items)
     assert tree.root.data == 2
     assert tree.root.left.data == 1
     assert tree.root.right.data == 3
     # TODO: Test structure of tree after each deletion
     print("TREE=", tree.root, tree.root.left, tree.root.right)
     tree.delete(1)
     print("TREE=", tree.root, tree.root.left, tree.root.right)
     assert tree.root.left is None
 def test_delete(self):
     tree = BinarySearchTree([2, 4])
     assert tree.height() == 1
     tree.delete(4)
     assert tree.height() == 0
     tree.delete(2)
     assert tree.height() == 0
     items = [18, 1, 53, 40, 63]
     tree.insert(10)
     tree = BinarySearchTree(items)
     tree.delete(1)
     assert tree.search(1) is None
     tree.delete(10)
     assert tree.search(10) is None
     tree.insert(57)
     tree.insert(98)
     tree.delete(63)
     assert tree.search(63) is None
    def test_delete_with_7_items(self):
        # Create a complete binary search tree of 7 items in level-order
        items = [4, 2, 6, 1, 3, 5, 7]
        tree = BinarySearchTree(items)
        # TODO: Test structure of tree after each deletion
        tree.delete(4)
        assert tree.root.data == 5
        assert tree.root.left.data == 2
        assert tree.root.right.data == 6
        assert len(tree.items_in_order()) == 6
        # assert ...
        # assert ...
        tree.delete(2)
        assert tree.root.data == 5
        assert tree.root.left.data == 3
        assert tree.root.right.data == 6
        assert len(tree.items_in_order()) == 5
        assert tree.items_in_order() == [1, 3, 5, 6, 7]

        tree.delete(7)
        assert tree.root.data == 5
        assert tree.root.left.data == 3
        assert tree.root.right.data == 6
        assert len(tree.items_in_order()) == 4
        assert tree.items_in_order() == [1, 3, 5, 6]
Ejemplo n.º 9
0
 def DISABLED_test_delete_with_7_items(self):
     # Create a complete binary search tree of 7 items in level-order
     items = [4, 2, 6, 1, 3, 5, 7]
     tree = BinarySearchTree(items)
     tree.delete(4)
     assert tree.root.data == 3
     assert tree.root.left.data == 2
     assert tree.root.right.data == 6
     assert tree.root.left.left.data == 1
     assert tree.root.left.right.data == None
     assert tree.root.right.right.data == 7
     assert tree.root.right.left.data == 5
     tree.delete(6)
     assert tree.root.data == 3
     assert tree.root.left.data == 2
     assert tree.root.right.data == 5
     assert tree.root.left.left.data == 1
     assert tree.root.left.right.data == None
     assert tree.root.right.right.data == 7
     assert tree.root.right.left.data == None
     tree.delete(7)
     assert tree.root.data == 3
     assert tree.root.left.data == 2
     assert tree.root.right.data == 5
     assert tree.root.left.left.data == 1
     assert tree.root.left.right.data == None
     assert tree.root.right.right.data == None
     assert tree.root.right.left.data == None
class TreeSet(AbstractSet):
    def __init__(self, elements=None):
        """Initialize this binary tree with the given data."""
        self.tree = BinarySearchTree()
        if elements is not None:
            for element in elements:
                self.add(element)

    @property
    def size(self):
        """ Makes size an attribute """
        return self.tree.size

    def __repr__(self):
        """Return a string representation of this binary tree node."""
        return 'Set({!r})'.format(self.tree.items_in_order())

    def contains(self, item):
        """ Checks if item is in the set
            Time Complexity: O(logN) only grows in relation to the #node vs height
            starts fast/heavy then peeks with a lot for a long time"""
        return self.tree.contains(item)

    def add(self, item):
        """ Insert one item to the set if it doesn't already exist 
            Time complexity: O(logN) based off contains then just O(1) to add"""
        if not self.contains(item):
            self.tree.insert(item)

    def remove(self, item):
        """ Check if item exists and remove it or raise Keyerror
            Time complexity: O() """
        if self.contains(item):
            self.tree.delete(item)
        else:
            raise ValueError(item, "Is not in this set")

    def items(self):
        return self.tree.items_in_order()
Ejemplo n.º 11
0
 def test_delete_with_7_items(self):
     # Create a complete binary search tree of 7 items in level-order
     items = [4, 2, 6, 1, 3, 5, 7]
     tree = BinarySearchTree(items)
     # TODO: Test structure of tree after each deletion
     tree.delete(4, tree.root)
     assert tree.root.data == 5
     assert tree.root.left.data == 2
     assert tree.root.right.data == 6
     tree.delete(3, tree.root)
     assert tree.root.data == 5
     assert tree.root.left.data == 2
     assert tree.root.right.data == 6
     tree.delete(5, tree.root)
     assert tree.root.data == 6
     assert tree.root.left.data == 2
     assert tree.root.right.data == 7
Ejemplo n.º 12
0
 def DISABLED_test_delete_with_3_items(self):
     # Create a complete binary search tree of 3 items in level-order
     items = [2, 1, 3]
     tree = BinarySearchTree(items)
     assert tree.root.data == 2
     assert tree.root.left.data == 1
     assert tree.root.right.data == 3
     tree.delete(2)
     assert tree.root.data == 3
     assert tree.root.left is 1
     assert tree.root.right is None
     tree.delete(1)
     assert tree.root.data == 3
     assert tree.root.left is None
     assert tree.root.right is None
     tree.delete(3)
     assert tree.root.data is None
     assert tree.root.left is None
     assert tree.root.right is None
Ejemplo n.º 13
0
 def test_delete_with_3_items(self):
     # Create a complete binary search tree of 3 items in level-order
     items = [2, 1, 3]
     tree = BinarySearchTree(items)
     assert tree.root.data == 2
     assert tree.root.left.data == 1
     assert tree.root.right.data == 3
     # TODO: Test structure of tree after each deletion
     tree.delete(2, tree.root)
     assert tree.root.data == 3
     assert tree.root.left.data == 1
     assert tree.root.right is None
     tree.delete(1, tree.root)
     assert tree.root.data == 3
     assert tree.root.left is None
     assert tree.root.right is None
     tree.delete(3, tree.root)  # cant delete the root.
     assert tree.root.data == 3
     assert tree.root.left is None
     assert tree.root.right is None
Ejemplo n.º 14
0
 def test_delete_with_3_items(self):
     # Create a complete binary search tree of 3 items in level-order
     items = [2, 1, 3]
     tree = BinarySearchTree(items)
     assert tree.root.data == 2
     assert tree.root.left.data == 1
     assert tree.root.right.data == 3
     # Test structure of tree after each deletion
     tree.delete(2)
     assert tree.size == 2
     assert tree.contains(1) is True
     assert tree.contains(3) is True
     tree.delete(1)
     assert tree.size == 1
     assert tree.contains(1) is False
     assert tree.contains(3) is True
     tree.delete(3)
     assert tree.size == 0
     assert tree.contains(1) is False
     assert tree.contains(3) is False
     assert tree.root is None
Ejemplo n.º 15
0
 def test_delete_with_3_items(self):
     # Create a complete binary search tree of 3 items in level-order
     items = [2, 1, 3]
     tree = BinarySearchTree(items)
     assert tree.contains(1)
     assert tree.contains(2)
     assert tree.contains(3)
     assert tree.root.data == 2
     # TODO: Test structure of tree after each deletion
     tree.delete(2)
     print(tree.root.data)
     assert tree.contains(1)
     assert tree.contains(3)
     assert tree.contains(2) == False
     tree.delete(1)
     assert tree.contains(1) == False
     assert tree.contains(3)
     assert tree.contains(2) == False
     tree.delete(3)
     print(tree)
     print(tree.root)
     assert tree.root is None
Ejemplo n.º 16
0
 def test_delete_with_7_items(self):
     # Create a complete binary search tree of 7 items in level-order
     items = [4, 2, 6, 1, 3, 5, 7]
     tree = BinarySearchTree(items)
     # Test structure of tree after each deletion
     tree.delete(4)
     assert tree.root.data == 5
     assert tree.root.left.data == 2
     assert tree.root.right.data == 6
     assert tree.root.right.right.data == 7
     assert tree.root.right.left is None
     tree.delete(2)
     assert tree.root.data == 5
     assert tree.root.left.data == 3
     assert tree.root.right.data == 6
     assert tree.root.left.right is None
     assert tree.root.left.left.data == 1
     tree.delete(6)
     assert tree.root.data == 5
     assert tree.root.left.data == 3
     assert tree.root.right.data == 7
     assert tree.root.right.right is None
     assert tree.root.right.left is None
 def DISABLED_test_delete_with_7_items(self):
     # Create a complete binary search tree of 7 items in level-order
     items = [4, 2, 6, 1, 3, 5, 7]
     tree = BinarySearchTree(items)
     # TODO: Test structure of tree after each deletion
     tree.delete(4)
     assert tree.root.data == ...
     assert tree.root.left.data == ...
     assert tree.root.right.data == ...
     assert ...
     assert ...
     tree.delete(...)
     assert tree.root.data == ...
     assert tree.root.left.data == ...
     assert tree.root.right.data == ...
     assert ...
     assert ...
     tree.delete(...)
     assert tree.root.data == ...
     assert tree.root.left.data == ...
     assert tree.root.right.data == ...
     assert ...
     assert ...
Ejemplo n.º 18
0
class Set_Tree(object):
    def __init__(self, elements=None):
        self.tree = BinarySearchTree()
        self.size = 0
        if elements is not None:
            for element in elements:
                self.add(element)

    def __repr__(self):
        """Return a string representation of this hash table."""
        return 'Set_Tree({!r})'.format(self.tree.items_in_order())

    def __iter__(self):
        for item in self.tree.items_in_order():
            yield item

    def contains(self, element):
        '''
        Return true if this set contains the given element, False otherwise
        Time complexity: O(logn)
        Space complexity: O(logn) if recursive, O(1) if iterative
        '''
        return self.tree.contains(element)

    def add(self, element):
        '''
        Adds element to a set if it's not already in the set
        Time complexity: O(logn).O(logn)
        Space complexity: O(1)
        '''
        #if the element is not already in the set, insert it
        if not self.contains(element):  #O(logn)
            self.tree.insert(element)  #O(logn)
            self.size += 1

    def remove(self, element):
        '''
        Removes the element from the set, if it exists
        Time complexity: O(n) + O(logn) = O(n)
        Space complexity: O(n) getting the inorder item to find successor
        '''
        #delete from the set, if it's in the set
        #else raise key error
        if self.contains(element):  #O(1)
            self.tree.delete(element)  #O(n)
            self.size -= 1
        else:
            raise KeyError

    def union(self, other_set):
        '''
        Return a new set that is the union of this set and other_set
        Time complexity: O(mlogm) + O(nlogn)
        Space complexity: O(m+n)
        '''
        #create a new set with items of self
        new_set = Set_Tree(self)  #O(mlogm)
        #then add everything from other_set to new_set
        for element in other_set:  #O(n)
            new_set.add(element)  #O(logn)
        return new_set

    def intersection(self, other_set):
        '''
        Return a new set that is the intersection of this set and other_set
        Time complexity: O(mlogn).O(mlog(min(m,n)))
        Space complexity: O(log(min(m,n)))
        '''
        #create new set
        new_set = Set_Tree()  #O(1)
        ##########check to see which one is smaller####
        #for item in set1
        #if it's in set2, add it to the new_set
        for item in self:  #O(m)
            if other_set.contains(item):  #O(logn)
                new_set.add(item)  #O(log(min(m,n)))
        return new_set

    def difference(self, other_set):
        '''
        Return a new set that is the difference of this set and other_set
        Time complexity: O(mlog(mn))
        Space complexity: O(log(min(m,n)))
        '''
        #create a new set
        new_set = Set_Tree()
        #if item is in set1 but not in set2, add it
        for item in self:  #O(m)
            if not other_set.contains(
                    item):  #O(logn) #if other set doesn't contain item O(logn)
                new_set.add(item)  #O(1)
        return new_set

    def is_subset(self, other_set):
        '''
        Return a boolean indicating whether other_set is a subset of this set
        Time complexity: O(nlogm)
        Space complexity: O(n)
        '''
        if other_set.size > self.size:  #it can't be a subset if it has more items
            return False
        for element in other_set:  #O(n)
            if not self.contains(element):  #O(logm)
                return False  #not all element of set2 are in set1
        return True  #finished the loop, all elements are in set1
Ejemplo n.º 19
0
 def test_delete_with_7_items(self):
     # Create a complete binary search tree of 7 items in level-order
     items = [4, 2, 6, 1, 3, 5, 7]
     tree = BinarySearchTree(items)
     # Test structure of tree after each deletion
     tree.delete(4)
     assert tree.size == 6
     assert tree.contains(2) is True
     assert tree.contains(6) is True
     assert tree.contains(1) is True
     assert tree.contains(3) is True
     assert tree.contains(5) is True
     assert tree.contains(7) is True
     tree.delete(2)
     assert tree.size == 5
     assert tree.contains(2) is False
     assert tree.contains(6) is True
     assert tree.contains(1) is True
     assert tree.contains(3) is True
     assert tree.contains(5) is True
     assert tree.contains(7) is True
     tree.delete(6)
     assert tree.size == 4
     assert tree.contains(2) is False
     assert tree.contains(6) is False
     assert tree.contains(1) is True
     assert tree.contains(3) is True
     assert tree.contains(5) is True
     assert tree.contains(7) is True
     tree.delete(1)
     assert tree.size == 3
     assert tree.contains(2) is False
     assert tree.contains(6) is False
     assert tree.contains(1) is False
     assert tree.contains(3) is True
     assert tree.contains(5) is True
     assert tree.contains(7) is True
     tree.delete(3)
     assert tree.size == 2
     assert tree.contains(2) is False
     assert tree.contains(6) is False
     assert tree.contains(1) is False
     assert tree.contains(3) is False
     assert tree.contains(5) is True
     assert tree.contains(7) is True
     tree.delete(5)
     assert tree.size == 1
     assert tree.contains(2) is False
     assert tree.contains(6) is False
     assert tree.contains(1) is False
     assert tree.contains(3) is False
     assert tree.contains(5) is False
     assert tree.contains(7) is True
     tree.delete(7)
     assert tree.size == 0
     assert tree.contains(2) is False
     assert tree.contains(6) is False
     assert tree.contains(1) is False
     assert tree.contains(3) is False
     assert tree.contains(5) is False
     assert tree.contains(7) is False
     assert tree.root is None
    def test_delete(self):
        items = [4, 2, 6, 1, 3, 5, 7]
        # Balanced tree
        tree = BinarySearchTree(items)
        assert tree.items_level_order() == [4, 2, 6, 1, 3, 5, 7]
        assert tree.size == 7
        # Delete leaves
        tree.delete(7)
        assert tree.items_level_order() == [4, 2, 6, 1, 3, 5]
        assert tree.size == 6
        tree.delete(1)
        assert tree.items_level_order() == [4, 2, 6, 3, 5]
        assert tree.size == 5
        # Delete nodes with one branch
        tree.delete(2)
        assert tree.items_level_order() == [4, 3, 6, 5]
        assert tree.size == 4
        tree.delete(6)
        assert tree.items_level_order() == [4, 3, 5]
        assert tree.size == 3

        # Reset
        tree = BinarySearchTree(items)
        assert tree.items_level_order() == [4, 2, 6, 1, 3, 5, 7]
        assert tree.size == 7
        # Delete double branch
        tree.delete(2)
        assert tree.items_level_order() == [4, 1, 6, 3, 5, 7]
        assert tree.size == 6
        tree.delete(6)
        assert tree.items_level_order() == [4, 1, 5, 3, 7]
        assert tree.size == 5

        # Reset
        tree = BinarySearchTree(items)
        assert tree.items_level_order() == [4, 2, 6, 1, 3, 5, 7]
        assert tree.size == 7
        # Delete root
        tree.delete(4)
        print(tree.items_level_order())
        assert tree.items_level_order() == [3, 2, 6, 1, 5, 7]

        # Larger tree
        items = [8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15]
        tree = BinarySearchTree(items)
        tree.delete(8)
        assert tree.items_level_order() == [
            7, 4, 12, 2, 6, 10, 14, 1, 3, 5, 9, 11, 13, 15
        ]
        tree.delete(7)
        print(tree.items_level_order())
        assert tree.items_level_order() == [
            6, 4, 12, 2, 5, 10, 14, 1, 3, 9, 11, 13, 15
        ]
        tree.delete(6)
        print(tree.items_level_order())
        assert tree.items_level_order() == [
            5, 4, 12, 2, 10, 14, 1, 3, 9, 11, 13, 15
        ]
Ejemplo n.º 21
0
class TreeSet:
    def __init__(self, elements=None):
        """initialize a new empty set structure, and add each element if a sequence is given
        size - property that tracks the number of elements in constant time"""
        self.tree = BinarySearchTree()
        self.size = 0
        if elements is not None:
            for element in elements:
                self.add(element)

    def length(self):
        return self.size

    def contains(self, element):
        """return a boolean indicating whether element is in this set"""
        if self.tree.contains(element):
            return True
        # return self.tree.contains(element) is not None
        return False

    def add(self, element):
        """add element to this set, if not present already"""
        if self.contains(element):
            raise ValueError('Cannot add element to set again: {}'.format(element))
        else:
            self.tree.insert(element)
            self.size += 1

    def remove(self, element):
        """remove element from this set, if present, or else raise KeyError"""
        self.tree.delete(element)
        self.size -= 1

    def union(self, other_set):
        """return a new set that is the union of this set and other_set"""
        union_set = self.tree.items_in_order()
        for element in other_set.tree.items_in_order():
            if element not in union_set:
                union_set.append(element)

        return TreeSet(union_set)

    def intersection(self, other_set):
        """return a new set that is the intersection of this set and other_set"""
        intersection_set = TreeSet()
        for element in self.tree.items_in_order():
            if other_set.contains(element):
                intersection_set.add(element)

        return intersection_set

    def difference(self, other_set):
        """return a new set that is the difference of this set and other_set"""
        difference_set = TreeSet()
        for element in other_set.tree.items_in_order():
            if self.tree.contains(element) is False:
                difference_set.add(element)

        for element in self.tree.items_in_order():
            if other_set.contains(element) is False:
                difference_set.add(element)


        return difference_set

    def is_subset(self, other_set):
        """return a boolean indicating whether this set is a subset of other_set"""
        if other_set.size < self.size:
            return False

        for element in self.tree.items_in_order():
            if other_set.contains(element) is False:
                return False

        return True
Ejemplo n.º 22
0
 def test_delete_with_7_items(self):
     # Create a complete binary search tree of 7 items in level-order
     items = [4, 2, 6, 1, 3, 5, 7]
     tree = BinarySearchTree(items)
     # Test structure of tree after each deletion
     assert tree.size == 7
     assert tree.root.data == 4
     assert tree.root.left.data == 2
     assert tree.root.right.data == 6
     tree.delete(4)
     assert tree.root.data == 3
     assert tree.root.left.data == 2
     assert tree.root.right.data == 6
     assert tree.size == 6
     tree.delete(1)
     assert tree.root.data == 3
     assert tree.root.left.data == 2
     assert tree.root.right.data == 6
     assert tree.size == 5
     tree.delete(3)
     assert tree.root.data == 2
     assert tree.root.left is None
     assert tree.root.right.data == 6
     assert tree.size == 4
     with pytest.raises(ValueError):
         tree.delete(1)
     tree.delete(7)
     assert tree.root.data == 2
     assert tree.root.left is None
     assert tree.root.right.data == 6
     assert tree.size == 3
     tree.delete(2)
     assert tree.root.data == 6
     assert tree.root.left.data == 5
     assert tree.root.right is None
     assert tree.size == 2
     tree.delete(5)
     assert tree.root.data == 6
     assert tree.root.left is None
     assert tree.root.right is None
     assert tree.size == 1
     tree.delete(6)
     assert tree.root is None
     assert tree.size == 0
Ejemplo n.º 23
0
class Setree:
    def __init__(self, ls=None):
        self.tree = BinarySearchTree()
        self.size = 0
        if ls is not None:
            for item in ls:
                self.add(item)

    def add(self, item):
        '''Add an item to the set. O(log(n))'''
        if self.contains(item) is False:
            self.tree.insert(item)
            self._update_size()

    def contains(self, item):
        '''Check if set contains item. O(log(n))'''
        return self.tree.contains(item)

    def remove(self, item):
        '''Remove item from set or ValueError O(log(n))'''
        self.tree.delete(item)
        self._update_size()

    def union(self, nset):
        '''Create a new set with elements of both sets O((m+n)*log(m+n))'''
        return Setree(self.in_order() + nset.in_order())

    def intersection(self, nset):
        '''Create a new set with elements that are in both sets O(min(m,n)*log(n)*log(m))'''
        if self.size > nset.size:
            small = nset
            big = self
        else:
            big = nset
            small = self
        nnset = Setree()
        for item in small.in_order():
            if big.contains(item):
                nnset.add(item)
        return nnset

    def is_subset(self, nset):
        '''Check if each item in one set is in this set O(n*log(n)*log(m))'''
        if self.size < nset.size:
            return False
        items = nset.in_order()
        for i in items:
            if self.contains(i) is False:
                return False
        return True

    def difference(self, nset):
        '''Check for each item in this is not in another set O(m*log(n))'''
        return Setree(
            [i for i in self.in_order() if nset.contains(i) is False])

    def in_order(self):
        """returns all of the values in a set in sorted order O(m)"""
        return self.tree.items_in_order()

    def _update_size(self):
        """Updates the size."""
        self.size = self.tree.size

    def bad_balance(self):
        print('Previous height:')
        print(self._height())
        queue = LinkedQueue()
        ls = self.in_order()
        self._binary_sorter(ls, queue.enqueue)
        self.tree = BinarySearchTree()
        count = 1
        while queue.front() is not None:
            self.add(ls[queue.dequeue()])
            count += 1
        print('Balanced height:')
        print(self._height())
        print(count)

    def _binary_sorter(self, ls, visit, last=None, left=None, right=None):
        if left is None:
            left, right = 0, len(ls) - 1
        midpoint = left + ((right - left) // 2)
        if midpoint != last:
            visit(midpoint)
        if midpoint != last:
            self._binary_sorter(ls, visit, midpoint, midpoint + 1, right)
        if midpoint != last:
            self._binary_sorter(ls, visit, midpoint, left, midpoint - 1)

    def _height(self):
        return self.tree.root.height_f()
Ejemplo n.º 24
0
 def test_delete_with_7_items(self):
     # Create a complete binary search tree of 7 items in level-order
     items = [4, 2, 6, 1, 3, 5, 7]
     tree = BinarySearchTree(items)
     # TODO: Test structure of tree after each deletion
     tree.delete(4)
     assert tree.contains(2)
     assert tree.contains(1)
     assert tree.contains(6)
     assert tree.contains(3)
     assert tree.contains(5)
     assert tree.contains(7)
     tree.delete(6)
     assert tree.contains(5)
     assert tree.contains(3)
     assert tree.contains(2)
     assert tree.contains(7)
     assert tree.contains(1)
     tree.delete(3)
     assert tree.contains(2)
     assert tree.contains(5)
     assert tree.contains(1)
     assert tree.contains(7)
     tree.delete(7)
     assert tree.contains(2)
     assert tree.contains(5)
     assert tree.contains(1)
     tree.delete(5)
     assert tree.contains(2)
     assert tree.contains(1)
     tree.delete(1)
     assert tree.contains(2)
     tree.delete(2)
     assert tree.root is None
Ejemplo n.º 25
0
class TreeSet:
    def __init__(self, items=None):
        self.tree = BinarySearchTree()
        if items is not None:
            for item in items:
                self.add(item)

    def __len__(self):
        return len(self.tree)

    def __contains__(self, item):
        return item in self.tree

    def __iter__(self):
        for item in self.tree.items_in_order():
            yield item

    def add(self, item):
        if item not in self.tree:
            self.tree.insert(item)

    def remove(self, item):
        self.tree.delete(item)

    def _smaller_larger_pair(self, tree_1, tree_2):
        if len(tree_1) < len(tree_2):
            return tree_1, tree_2

        return tree_2, tree_1

    def intersection(self, other_set):
        new_set = TreeSet()
        smaller, larger = self._smaller_larger_pair(self.tree, other_set.tree)
        for item in smaller.items_pre_order():
            if item in larger:
                new_set.add(item)

        return new_set

    def _alternating_generator(self, tree1, tree2):
        items_1 = tree1.items_pre_order()
        items_2 = tree2.items_pre_order()
        for item_1, item_2 in zip(items_1, items_2):
            yield item_1
            yield item_2

    def union(self, other_set):
        new_set = TreeSet()
        for item in self._alternating_generator(self.tree, other_set.tree):
            new_set.add(item)

        return new_set

    def difference(self, other_set):
        new_set = TreeSet()
        for item in self.tree.items_pre_order():
            if item not in other_set:
                new_set.add(item)

        return new_set

    def is_subset(self, other_set):
        if len(self) > len(other_set):
            return False

        for item in self.tree.items_pre_order():
            if not other_set.contains(item):
                return False

        return True
Ejemplo n.º 26
0
 def test_delete_with_7_items(self):
     # Create a complete binary search tree of 7 items in level-order
     items = [4, 2, 6, 1, 3, 5, 7]
     tree = BinarySearchTree(items)
     tree.delete(4)
     assert tree.root.data == 5
     assert tree.root.left.data == 2
     assert tree.root.right.data == 6
     assert tree.size == 6
     tree.delete(2)
     assert tree.root.data == 5
     assert tree.root.left.data == 3
     assert tree.root.right.data == 6
     assert tree.size == 5
     tree.delete(6)
     assert tree.root.data == 5
     assert tree.root.left.data == 3
     assert tree.root.right.data == 7
     assert tree.size == 4
     tree.delete(1)
     assert tree.root.data == 5
     assert tree.root.left.data == 3
     assert tree.root.right.data == 7
     assert tree.size == 3
     tree.delete(3)
     assert tree.root.data == 5
     assert tree.root.left is None
     assert tree.root.right.data == 7
     assert tree.size == 2
     tree.delete(5)
     assert tree.root.data == 7
     assert tree.root.left is None
     assert tree.root.right is None
     assert tree.size == 1
     tree.delete(7)
     assert tree.root.data is None
     assert tree.root.left is None
     assert tree.root.right is None
     assert tree.size == 0
Ejemplo n.º 27
0
class Set:
    def __init__(self, items):
        self.set = BinarySearchTree()
        self.size = 0
        for item in items:
            self.add(item)

    def __eq__(self, other):
        return self.set.items_in_order() == other.set.items_in_order()

    def contains(self, item):
        '''Check what items are in the set'''
        return self.set.contains(item)

        # Time complexity: O(log n)

    def add(self, item):
        '''Add an item to a set'''
        if self.set.contains(item) != True:
            self.set.insert(item)
            self.size += 1

        # Time Complexity: O(log n)

    def remove(self, item):
        '''Remove item from a set'''
        return self.set.delete(item)

        # Time Complexity: O(log n)

    def union(self, other_set):
        '''Merges sets together, but removes duplicates'''
        unionset = Set(self.set.items_in_order() +
                       other_set.set.items_in_order())
        return unionset

        # Time Complexity: O(m + n)

    def intersection(self, other_set):
        '''Finds the most common elements in both sets'''
        # if item is present in self.set and other_set:
        #     return item
        intersectionitems = []
        for item in self.set.items_in_order():
            if other_set.contains(item) == True:
                intersectionitems.append(item)
        intersectionset = Set(intersectionitems)
        return intersectionset
        #check if item is in otherset using contains
        #if it is add to intersectionitems
        #create a new set out of intersectionitems and return it

    def difference(self, other_set):
        '''Checks what items are present in one set that are not present in the other'''
        differenceitems = []
        for item in self.set.items_in_order():
            if other_set.contains(item) == False:
                differenceitems.append(item)
        differenceset = Set(differenceitems)
        return differenceset

        # Time Complexity: O(m + n)

    def is_subset(self, other_set):
        '''Checks if a set is a subset of another set'''
        for item in self.set.items_in_order():
            if other_set.contains(item) == False:
                return False
        return True
Ejemplo n.º 28
0
class TreeSet(object):
    """Class for sets implemented with binary trees"""
    def __init__(self, items=None):
        """Initialize a new Set"""
        self.tree = BinarySearchTree(items)
        # self.size = self.tree.size

    def __repr__(self):
        """Return a string representation of this set"""
        items = ['({!r})'.format(item) for item in self.tree.items_in_order()]
        return ', '.join(items)

    def __iter__(self):
        """Allow the set to be iterated over (i.e. in for loops)"""
        return iter([value for value in self.tree.items_level_order()])

    def __eq__(self, other):
        """Allow sets to be compared to other sets"""
        return self.tree.items_in_order() == other.tree.items_in_order()

    @property
    def size(self):
        """Use tree size property"""
        return self.tree.size

    def contains(self, item):
        """Return a boolean indicating whether item is in this set
        Best case time complexity: O(1) if item is in the tree root
        Worst case: O(logn) if item is a leaf
        """
        return self.tree.search(item) is not None

    def add(self, item):
        """Add the item to the set if not present
        Best case time complexity: O(1) if tree is empty
        Worst case: O(n) if tree is poorly balanced
        """
        if not self.contains(item):
            self.tree.insert(item)

    def remove(self, item):
        """Remove element from this set, if present, or else raise KeyError
        Best case time complexity: O(1) if item is in the tree root
        Worst case: O(logn) if item isn't there
        """
        if not self.contains(item):
            raise KeyError("Item not found")
        else:
            self.tree.delete(item)

    def union(self, other_set):
        """Return a new set that is the union of this set and other_set
        Best and worst case time complexity: O(n+m), where n is the size of
        self, and m is the size of other_set, because every item has to
        be accounted for
        """
        new_set = TreeSet(self)
        for item in other_set:
            new_set.add(item)
        return new_set

    def intersection(self, other_set):
        """Return a new set that is the intersection of this and other_set
        Best and worst case time complexity: O(m) where m is the size of
        other_set, because it iterates over the other set.
        """
        new_set = TreeSet()
        for item in other_set:
            if self.contains(item):
                new_set.add(item)
        return new_set

    def difference(self, other_set):
        """Return a new set that is the difference of this set and other_set
        Best and worst case time complexity: O(n + logm) where n is the size of
        self, and m is the size of other_set, because it iterates over self and
        checks if other_set contains the items
        """
        new_set = TreeSet()
        for item in self:
            if not other_set.contains(item):
                new_set.add(item)
        return new_set

    def is_subset(self, other_set):
        """Return a boolean indicating if other_set is a subset of this
        Best case time complexity: O(1) if other_set is larger than self
        Worst case: O(m) where m is the size of other_set, as it has to
        iterate over each element of it
        """
        if other_set.size > self.size:
            return False

        for item in other_set:
            if not self.contains(item):
                return False

        return True
class Set:
    def __init__(self, elements=None):
        self.tree = BinarySearchTree()
        self.size = 0
        if elements is not None:
            for elm in elements:
                self.add(elm)

    def size(self):
        return self.tree.size

    def __iter__(self):
        return self

    def contains(self, element):
        if self.tree.contains(element):
            return True
        return False

    def add(self, element):
        if self.contains(element):
            raise ValueError("Cannot add element to Set again")
        else:
            self.tree.insert(element)
            self.size += 1

    def remove(self, element):
        self.tree.delete(element)
        self.size -= 1

    def union(self, other_set):
        """TODO: Running time: O(n*k), have to visit every node
        TODO: Memory usage: O(n+k) nodes are stored on stack"""
        result = self.tree.items_in_order()
        for elm in other_set.tree.items_in_order():
            if elm not in result:
                result.append(elm)
        return Set(result)

    def intersection(self, other_set):
        """TODO: Running time: O(n), have to visit every node
        TODO: Memory usage: O(n+k) nodes are stored on stack"""
        result = Set()
        for elm in self.tree.items_in_order():
            if other_set.contains(elm):
                result.add(elm)
        return result

    def difference(self, other_set):
        """TODO: Running time: O(n), have to visit every node
        TODO: Memory usage: O(n+k) nodes are stored on stack"""
        result = Set()
        for elm in self.tree.items_in_order():
            if not other_set.contains(elm):
                result.add(elm)
        for elm in other_set.tree.items_in_order():
            if elm in result.tree.items_in_order():
                result.remove(elm)
        return result

    def is_subset(self, other_set):
        """TODO: Running time: O(n) worst, O(1 best), have to visit every node
        TODO: Memory usage: O(n+k) nodes are stored on stack"""
        if self.size > other_set.size:
            return False

        for elm in self.tree.items_in_order():
            if not other_set.tree.contains(elm):
                return False
        return True
Ejemplo n.º 30
0
class TreeSet(object):
    """Initialize a new empty set structure, and add each element if a sequence is given"""
    def __init__(self, elements=None):
        self.tree = BinarySearchTree()
        self.element = BinaryTreeNode
        if elements is not None:
            for element in elements:
                self.add(element)

    @property
    def size(self):
        """Property that tracks the number of elements in constant time"""
        return self.tree.size

    def contains(self, element):
        """return a boolean indicating whether element is in this set
        Running time: O(log n) since we just search through a binary tree"""
        return self.tree.contains(element)

    def add(self, element):
        """add element to this set, if not present already
        Running time: O(log n) because we must binary search"""
        if self.tree.contains(element):
            raise KeyError(f'{element} is already in tree.')
        else:
            self.tree.insert(element)

    def remove(self, element):
        """remove element from this set, if present, or else raise KeyError
        Running time: 
        Best Case: O(h) because we have to either scale the tree or move everything down
        once found.
        Worst Case: O(n) because the element could be the last we check in the tree."""
        if self.tree.contains(element) != True:
            raise KeyError(f'No such element exists: {element}')
        else:
            self.tree.delete(element)

    def union(self, other_set):
        """return a new set that is the union of this set and other_set
        Best and worst case: (m + n) * log m because we add the length of each set to the time of the .add calls"""
        # m log m + n*2logm = (m + 2n) * log m =
        # (m + n) * log m
        new_set = TreeSet()
        for element in self.tree.items_pre_order():  # O(h(self))
            new_set.add(element)  # + O(m)

        # Adds remaining other_set elements
        for element in other_set.tree.items_pre_order():
            if not new_set.contains(element):  # O(log m)
                new_set.add(element)  # +O(log m)

        return new_set

    def intersection(self, other_set):
        """return a new set that is the intersection of this set and other_set
        Best case/worst case: O(log n) due to binary search"""
        new_set = TreeSet()
        for element in self.tree.items_in_order():
            if other_set.contains(element):
                new_set.add(element)
        return new_set

    def difference(self, other_set):
        """return a new set that is the difference of this set and other_set
        Best/Worst case: O(n) because we require checking all nodes"""
        new_set = TreeSet()
        for element in self.tree.items_in_order():
            new_set.add(element)

        for element in other_set.tree.items_in_order():
            if new_set.contains(element):
                new_set.remove(element)
        return new_set

    def is_subset(self, other_set):
        """return a boolean indicating whether other_set is a subset of this set
        Best case:e O(1), incase the size is bigger than other_set and we don't need to do anything.
        Worst case: O(n), if we must traverse through all nodes"""
        if self.size > other_set.size:
            return False

        for element in other_set.tree.items_in_order():
            if not self.contains(element):
                return False

        return True