コード例 #1
0
 def test_items_in_order_with_3_strings(self):
     # Create a complete binary search tree of 3 strings in level-order
     items = ['B', 'A', 'C']
     tree = BinarySearchTree(items)
     # Ensure the in-order traversal of tree items is ordered correctly
     assert tree.items_in_order() == ['A', 'B', 'C']
コード例 #2
0
 def test_items_in_order_with_7_numbers(self):
     # Create a complete binary search tree of 7 items in level-order
     items = [4, 2, 6, 1, 3, 5, 7]
     tree = BinarySearchTree(items)
     # Ensure the in-order traversal of tree items is ordered correctly
     assert tree.items_in_order() == [1, 2, 3, 4, 5, 6, 7]
コード例 #3
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
コード例 #4
0
def tree_sort(items):
    tree = BinarySearchTree(items)
    items[:] = tree.items_in_order()
コード例 #5
0
def tree_sort(items):
    binary_tree = BinarySearchTree()  # constant time
    for item in items:  # n iterations
        binary_tree.insert(item)  # O(n)
    print(binary_tree.items_in_order())
    binary_tree.items_in_order()
コード例 #6
0
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
コード例 #7
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
コード例 #8
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
コード例 #9
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
コード例 #10
0
    def test_delete(self):
        """
             10
           /    \
          5     15
         / \   /  \
        3  8  14  20
          / \
         7   9
        """
        items = [10, 5, 15, 20, 14, 3, 8, 7, 9]
        tree = BinarySearchTree()
        for item in items:
            tree.insert(item)

        # First Case: Node we want to remove has two children
        tree.remove(10)
        """
             20
           /    \
          5     15
         / \   /  
        3  8  14  
          / \
         7   9
        """
        assert tree.root.data == 20

        with self.assertRaises(ValueError):
            tree.remove(10)

        # Second Case: Node we want to remove has no children, we a leaf
        tree.remove(3)
        """
             20
           /    \
          5     15
           \   /  
           8  14  
          / \
         7   9
        """

        with self.assertRaises(ValueError):
            tree.remove(3)

        # Third: Node we want to remove has one child
        tree.remove(5)
        """
             20
           /    \
          8      15
         / \    /  
        7   9  14  
        """

        print(tree.items_in_order())
        tree.remove(14)
        tree.remove(15)
        tree.remove(20)

        assert tree.root.data == 8

        assert tree.root.left.data == 8
コード例 #11
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
コード例 #12
0
def tree_sort(items):
    tree = BT(items)
    sorted_items = tree.items_in_order()
    return sorted_items
コード例 #13
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
コード例 #14
0
def tree_sort(items):
    item_tree = BinarySearchTree(items)
    print(item_tree.items_in_order())
    print(len(item_tree.items_in_order()), len(items))
    items[:] = item_tree.items_in_order()
コード例 #15
0
ファイル: test.py プロジェクト: e-bushi/Core-Data_Structures
from sorting import is_sorted
from binarytree import BinarySearchTree

items = [5, 8, 2, 0, 11, 4, 3, 9]
tree = BinarySearchTree(items)

print(tree.items_in_order())