Пример #1
0
def _post_order_helper(node_lst: List[ReadNode],
                       root_index: int, flag: bool = True,
                       right_index: int = 0) -> HuffmanTree:
    """
    A helper function that generates a tree based on <node_lst> ReadNodes,
    and uses <root_index> and <flag> and <right_index> to do so.
    """
    # if internal node
    if node_lst[root_index].l_type == 1 and flag:

        # Making Tree
        tree = HuffmanTree(None)

        tree.number = root_index - 1 - right_index

        # Creating Left and Right Trees
        tree.right = _post_order_helper(node_lst, tree.number, False)

        right_index = _find_height(tree.right)

        if right_index is None:
            right_index = 0
        else:
            right_index = len(right_index)

        tree.left = _post_order_helper(
            node_lst, tree.number, True, right_index)

        return tree

    elif node_lst[root_index].r_type == 1 and not flag:
        # Making Tree
        tree = HuffmanTree(None)
        tree.number = root_index - 1

        # Creating Left and Right Trees
        tree.right = _post_order_helper(node_lst, tree.number, False)

        right_index = _find_height(tree.right)

        if right_index is None:
            right_index = 0
        else:
            right_index = len(right_index)

        tree.left = _post_order_helper(
            node_lst, tree.number, True, right_index)

        return tree

    elif node_lst[root_index].l_type == 0 and flag:
        return HuffmanTree(node_lst[root_index].l_data)

    elif node_lst[root_index].r_type == 0 and not flag:
        return HuffmanTree(node_lst[root_index].r_data)

    return HuffmanTree(None)
Пример #2
0
def number_nodes(tree: HuffmanTree) -> None:
    """ Number internal nodes in <tree> according to postorder traversal. The
    numbering starts at 0.
    >>> leftleft = HuffmanTree(None, HuffmanTree(4), HuffmanTree(12))
    >>> left = HuffmanTree(None, leftleft, HuffmanTree(2))
    >>> right = HuffmanTree(None, HuffmanTree(9), HuffmanTree(10))
    >>> tree = HuffmanTree(None, left, right)
    >>> number_nodes(tree)
    >>> tree.left.left.number
    0
    >>> tree.left.number
    1
    >>> tree.right.number
    2
    >>> tree.number
    3
    """
    curr_number = 0
    list_of_nodes = []
    dict_of_nodes = find_internal_nodes(tree, 0)
    for el in dict_of_nodes:
        list_of_nodes.append(el)
    list_of_nodes.reverse()
    for el in list_of_nodes:
        for tree in dict_of_nodes[el]:
            tree.number = curr_number
            curr_number += 1
Пример #3
0
def _clean_huff_tree(tree: HuffmanTree):
    """
    convert all HuffmanTree.number to None after
    using it to keep list sorted
    """
    if tree:
        _clean_huff_tree(tree.left)
        _clean_huff_tree(tree.right)
        tree.number = None
Пример #4
0
def _number_nodes_helper(tree: HuffmanTree, number: int = 0) -> int:
    """
    A helper function that uses a <tree> to <number> the internal nodes.
    """
    if tree.is_leaf():
        return number - 1
    else:
        number = _number_nodes_helper(tree.left, number) + 1
        number = _number_nodes_helper(tree.right, number) + 1
        tree.number = number
        return number
Пример #5
0
def _gen_tree_helper(node_lst: List[ReadNode],
                     root_index: int, flag: bool = True) -> HuffmanTree:
    """
    A helper function that generates a tree based on <node_lst> ReadNodes,
    and uses <root_index> and <flag> to do so.
    """
    # if internal node
    if node_lst[root_index].l_type == 1 and flag:

        # Making Tree
        tree = HuffmanTree(None)
        tree.number = node_lst[root_index].l_data

        # Creating Left and Right Trees
        tree.left = _gen_tree_helper(node_lst, tree.number, True)
        tree.right = _gen_tree_helper(node_lst, tree.number, False)

        return tree

    elif node_lst[root_index].r_type == 1 and not flag:
        # Making Tree
        tree = HuffmanTree(None)
        tree.number = node_lst[root_index].r_data

        # Creating Left and Right Trees
        tree.left = _gen_tree_helper(node_lst, tree.number, True)
        tree.right = _gen_tree_helper(node_lst, tree.number, False)

        return tree

    elif node_lst[root_index].l_type == 0 and flag:
        return HuffmanTree(node_lst[root_index].l_data)

    elif node_lst[root_index].r_type == 0 and not flag:
        return HuffmanTree(node_lst[root_index].r_data)

    return HuffmanTree(None)
Пример #6
0
def _recursive_numbering(tree: HuffmanTree, cur_num: list):
    """
    Algorithm that recursively builds and mutates the huff_map
    """
    if tree.is_leaf():  # dont number leaves
        return

    elif not tree:  # blank tree, graceful termiantion
        return

    else:

        _recursive_numbering(tree.left, cur_num)
        # then right
        _recursive_numbering(tree.right, cur_num)
        # finally root
        tree.number = cur_num[0]
        cur_num[0] += 1
Пример #7
0
def _post_order_set_none(tree: HuffmanTree) -> None:
    """"
    Sets all the internal nodes of a <tree> to None.

    >>> left = HuffmanTree(None, HuffmanTree(3, None, None), \
    HuffmanTree(2, None, None))
    >>> right = HuffmanTree(5)
    >>> tree = HuffmanTree(None, left, right)
    >>> _print_postorder(tree)

    >>> tree = build_huffman_tree(build_frequency_dict(b"helloworld"))
    >>> number_nodes(tree)
    >>> _print_postorder(tree)
    """

    if tree:
        _post_order_set_none(tree.left)
        _post_order_set_none(tree.right)
        tree.number = None
Пример #8
0
def number_nodes(tree: HuffmanTree) -> None:
    """ Number internal nodes in <tree> according to postorder traversal. The
    numbering starts at 0.

    >>> left = HuffmanTree(None, HuffmanTree(3), HuffmanTree(2))
    >>> right = HuffmanTree(None, HuffmanTree(9), HuffmanTree(10))
    >>> tree = HuffmanTree(None, left, right)
    >>> number_nodes(tree)
    >>> tree.left.number
    0
    >>> tree.right.number
    1
    >>> tree.number
    2
    """
    # cant be recursive because different in/out\
    # use list so we can mutate value

    if tree.is_leaf():
        # leafs arent given a number
        tree.number = None

    else:
        _recursive_numbering(tree, [0])
Пример #9
0
def build_huffman_tree(freq_dict: Dict[int, int]) -> HuffmanTree:
    """ Return the Huffman tree corresponding to the frequency dictionary
    <freq_dict>.

    Precondition: freq_dict is not empty.
    >>> freq =  {104: 1, 101: 1, 108: 3, 111: 2, 119: 1, 114: 1, 100: 1}
    >>> t = build_huffman_tree(freq) # do something with this!


    >>> freq = {2: 6, 3: 4, 7: 5}
    >>> t = build_huffman_tree(freq)
    >>> result = HuffmanTree(None, HuffmanTree(2), \
                             HuffmanTree(None, HuffmanTree(3), HuffmanTree(7)))
    >>> t == result
    True
    >>> import random
    >>> symbol = random.randint(0,255)
    >>> freq = {symbol: 6}
    >>> t = build_huffman_tree(freq)
    >>> any_valid_byte_other_than_symbol = (symbol + 1) % 256
    >>> dummy_tree = HuffmanTree(any_valid_byte_other_than_symbol)
    >>> result = HuffmanTree(None, HuffmanTree(symbol), dummy_tree)
    >>> t.left == result.left or t.right == result.right
    True
    >>> freq = {2: 6, 3: 4}
    >>> t = build_huffman_tree(freq)
    >>> result = HuffmanTree(None, HuffmanTree(3), HuffmanTree(2))
    >>> t == result
    True
    """
    if len(freq_dict) == 1:
        symbol = list(freq_dict.keys())[0]

        symbol_2 = random.randint(0, 255)
        while symbol_2 in freq_dict:  # can take infinite time...
            symbol_2 = random.randint(0, 255)

        left = HuffmanTree(symbol)
        right = HuffmanTree(symbol_2)

        return HuffmanTree(None, left, right)

    else:
        huff_list = []
        for key in freq_dict:  # n time
            new_huff = HuffmanTree(key)
            new_huff.number = freq_dict.get(key)
            huff_list.append(new_huff)

        while len(huff_list) > 1:  # n time

            # sort list to easily get 2 lowest
            _huffman_insertion_sort(huff_list)

            # get lowest 2
            low_0 = huff_list.pop(0)
            low_1 = huff_list.pop(0)

            new_huffman = HuffmanTree(None, low_0,
                                      low_1)  # left has higher fre
            new_huffman.number = low_0.number + low_1.number

            # add it
            huff_list.append(new_huffman)

        _clean_huff_tree(huff_list[0])
        return huff_list[0]
Пример #10
0
def __number_nodes_helper(tree: HuffmanTree, ranger: list) -> None:
    """Helper to number_nodes"""
    if tree is not None and tree.left and tree.right:
        __number_nodes_helper(tree.left, ranger)
        __number_nodes_helper(tree.right, ranger)
        tree.number = ranger.pop(0)