def find_code(int_, tree): '''Return the code corresponding to the symbol int in tree. @type int: int @type tree: HuffmanNode @rtype: str >>> a = HuffmanNode(None, HuffmanNode(None, HuffmanNode(1), \ HuffmanNode(3)), HuffmanNode(2)) >>> find_code(2, a) '1' ''' code = "" if tree.right and tree.left: if int_ in get_leaves(tree.left): code = '0' return code + find_code(int_, tree.left) elif int_ in get_leaves(tree.right): code = '1' return code + find_code(int_, tree.right) return code
def generate_tree_postorder(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes that the list represents a tree in postorder. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode >>> lst = [ReadNode(0, 20, 0, 16), ReadNode(0, 26, 0, 23), \ ReadNode(0, 15, 1, 0), ReadNode(1, 0, 1, 0)] >>> tree_example = HuffmanNode(None, HuffmanNode(None, \ HuffmanNode(20, None, None), HuffmanNode(16, None, None)), \ HuffmanNode(None, HuffmanNode(15, None, None), HuffmanNode(None, \ HuffmanNode(26, None, None), HuffmanNode(23, None, None)))) >>> tree_example == generate_tree_postorder(lst, 3) True """ if node_lst[root_index].l_type == 0 and node_lst[root_index].r_type == 0: node = HuffmanNode(None, HuffmanNode(node_lst[root_index].l_data), HuffmanNode(node_lst[root_index].r_data)) elif node_lst[root_index].l_type == 0 and node_lst[root_index].r_type == 1: node = HuffmanNode(None, HuffmanNode(node_lst[root_index].l_data), generate_tree_postorder(node_lst, (root_index - 1))) elif node_lst[root_index].l_type == 1 and node_lst[root_index].r_type == 0: node = HuffmanNode(None, generate_tree_postorder(node_lst, (root_index - 1)), HuffmanNode(node_lst[root_index].r_data)) else: right = generate_tree_postorder(node_lst, (root_index - 1)) number_nodes(right) new_index = (root_index - 1) - (right.number + 1) node = HuffmanNode(None, generate_tree_postorder(node_lst, new_index), right) number_nodes(node) return node
def get_leaves(tree): '''Return a list containing the symbols of leaves. @type tree: HuffmanNode @rtype: list[int] >>> a = HuffmanNode(None, HuffmanNode(None, HuffmanNode(1),\ HuffmanNode(3)), HuffmanNode(2)) >>> b = get_leaves(a) >>> b.sort() >>> b [1, 2, 3] ''' if not tree.left and not tree.right: return [tree.symbol] else: if tree.left and tree.right: return get_leaves(tree.left) + get_leaves(tree.right) elif tree.left: return get_leaves(tree.left) else: return get_leaves(tree.right)
def postorder_helper(node_lst, root_index): # helper function """ Return the tuple with root of the Huffman tree corresponding to node_lst[root_index]. The function assumes that the list represents a tree in postorder. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: tuple of (HuffmanNode, int) """ track_index, track_node = root_index, node_lst[root_index] tree = HuffmanNode() # assign variables for node_lst and root_lst if track_node.r_type == 0: # start traversing from right tree.right = HuffmanNode(track_node.r_data) # if leaf else: right = postorder_helper(node_lst, track_index - 1) # recurse down tree.right, track_index = right[0], right[1] # modify right # and track new corresponding index if track_node.l_type == 0: # start traversing left side tree.left = HuffmanNode(track_node.l_data) # if leaf else: # do recursion on left side now and modify tree and track index left = postorder_helper(node_lst, track_index - 1) tree.left, track_index = left[0], left[1] return tree, track_index # return tuple
def generate_tree_general(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes nothing about the order of the nodes in the list. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode """ tree = HuffmanNode(None, None, None) def helper4(node_lst, root_index, tree): """Helps modify the inputted tree, by adding Nodes from the given node_lst, and root_index. @param lst[ReadNode] node_lst a list of ReadNode objects @param root_index, int; the root of the tree @param tree, HuffmanNode tree @rtype: NoneType """ l_data = node_lst[root_index].l_data r_data = node_lst[root_index].r_data if node_lst[root_index].l_type == 0: tree.left = HuffmanNode(l_data) else: tree.left = HuffmanNode(None, None, None) helper4(node_lst, l_data, tree.left) if node_lst[root_index].r_type == 0: tree.right = HuffmanNode(r_data) else: tree.right = HuffmanNode(None, None, None) helper4(node_lst, r_data, tree.right) return helper4(node_lst, root_index, tree) return tree
def huffman_tree_helper(lst): """ Delete the first two nodes and their frequencies in lst, and append a new node from the sum of those two nodes. @param list of lists lst: @rtype: None """ # take a list of lists with each inner list representing a "node" while len(lst) > 1: # delete two lowest nodes store = [lst[0], lst[1]] lst.remove(lst[0]) lst.remove(lst[0]) count = 0 # find the sum for item in store: count += item[0] sum_list = [count, HuffmanNode(None, store[0][1], store[1][1])] # append the node of the sum to the double_list lst.append(sum_list) lst.sort()
def get_huffman_leaves(tree): '''Return the leaves in tree. @type tree: HuffmanNode @rtype: list[HuffmanNode] >>> a = HuffmanNode(None, HuffmanNode(None, HuffmanNode(1),\ HuffmanNode(3)), HuffmanNode(2)) >>> b = get_huffman_leaves(a) >>> b [HuffmanNode(1, None, None), HuffmanNode(3, None, None), HuffmanNode(2, \ None, None)] ''' if tree.is_leaf(): return [tree] else: if tree.left and tree.right: return get_huffman_leaves(tree.left) + \ get_huffman_leaves(tree.right) elif tree.left: return get_huffman_leaves(tree.left) else: return get_huffman_leaves(tree.right)
def number_nodes(tree): """ Number internal nodes in tree according to postorder traversal; start numbering at 0. @param HuffmanNode tree: a Huffman tree rooted at node 'tree' @rtype: NoneType >>> left = HuffmanNode(None, HuffmanNode(3), HuffmanNode(2)) >>> right = HuffmanNode(None, HuffmanNode(9), HuffmanNode(None, \ HuffmanNode(10))) >>> tree = HuffmanNode(None, left, right) >>> number_nodes(tree) >>> tree.left.number 0 >>> tree.right.right.number 1 >>> tree.right.number 2 >>> tree.number 3 """ list_ = find_internal(tree) for node in list_: node.number = list_.index(node)
def generate_tree_general(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes nothing about the order of the nodes in the list. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode #>>> lst = [ReadNode(1, 0, 1, 0), ReadNode(0, 5, 0, 7), \ #ReadNode(0, 10, 0, 12)] #>>> generate_tree_general(lst, 0) >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 1, 1, 0)] >>> generate_tree_general(lst, 2) HuffmanNode(None, HuffmanNode(None, HuffmanNode(10, None, None), \ HuffmanNode(12, None, None)), \ HuffmanNode(None, HuffmanNode(5, None, None), HuffmanNode(7, None, None))) """ nodes = {} for i in range(len(node_lst)): node = HuffmanNode(None) node.number = i nodes[i] = node # Sequences left and right 'branches' of Huffman Tree for i in range(len(node_lst)): if node_lst[i].l_type == 0: nodes[i].left = HuffmanNode(node_lst[i].l_data) else: nodes[i].left = nodes[node_lst[i].l_data] if node_lst[i].r_type == 0: nodes[i].right = HuffmanNode(node_lst[i].r_data) else: nodes[i].right = nodes[node_lst[i].r_data] # Root of tree becomes dict value at root_index tree = nodes[root_index] return tree
def generate_huffman(r_node): """ Return a HuffmanNode from a ReadNode. @param ReadNode r_node: a ReadNode to convert @rtype: HuffmanNode >>> huff = generate_huffman(ReadNode(0, 10, 0, 12)) >>> huff == HuffmanNode(None, HuffmanNode(10), HuffmanNode(12)) True >>> huff = generate_huffman(ReadNode(1, 0, 1, 0)) >>> huff == HuffmanNode(None, HuffmanNode(), HuffmanNode()) True """ if r_node.l_type == 0 and r_node.r_type == 0: return HuffmanNode(None, HuffmanNode(r_node.l_data), HuffmanNode(r_node.r_data)) elif r_node.l_type == 0 and r_node.r_type == 1: return HuffmanNode(None, HuffmanNode(r_node.l_data), HuffmanNode()) elif r_node.l_type == 1 and r_node.r_type == 0: return HuffmanNode(None, HuffmanNode(), HuffmanNode(r_node.r_data)) else: return HuffmanNode(None, HuffmanNode(), HuffmanNode())
def generate_tree_general(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes nothing about the order of the nodes in node_lst. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in 'node_lst' @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 1, 1, 0)] >>> generate_tree_general(lst, 2) HuffmanNode(None, HuffmanNode(None, HuffmanNode(10, None, None), \ HuffmanNode(12, None, None)), \ HuffmanNode(None, HuffmanNode(5, None, None), HuffmanNode(7, None, None))) """ tree = HuffmanNode(None) if len(node_lst) == 0: return current = node_lst[root_index] if current.l_type == 0 and current.r_type == 0: tree.left = HuffmanNode(current.l_data) tree.right = HuffmanNode(current.r_data) if current.l_type == 0: tree.left = HuffmanNode(current.l_data) if current.r_type == 0: tree.right = HuffmanNode(current.r_data) if current.l_type == 1: tree.left = generate_tree_general(node_lst, current.l_data) if current.r_type == 1: tree.right = generate_tree_general(node_lst, current.r_data) return tree
def generate_huffman(r_node): """ Return a HuffmanNode from a ReadNode. @param ReadNode r_node: a ReadNode to convert @rtype: HuffmanNode >>> huff = generate_huffman(ReadNode(0, 5, 0, 7)) >>> huff == HuffmanNode(None, HuffmanNode(5), HuffmanNode(7)) True >>> huff = generate_huffman(ReadNode(1, 1, 1, 0)) >>> huff == HuffmanNode(None, HuffmanNode(), HuffmanNode()) True >>> huff.left.number 1 >>> huff.right.number 0 """ if r_node.l_type == 0 and r_node.r_type == 0: return HuffmanNode(None, HuffmanNode(r_node.l_data), HuffmanNode(r_node.r_data)) elif r_node.l_type == 0 and r_node.r_type == 1: huff_node = HuffmanNode(None, HuffmanNode(r_node.l_data), HuffmanNode()) huff_node.right.number = r_node.r_data return huff_node elif r_node.l_type == 1 and r_node.r_type == 0: huff_node = HuffmanNode(None, HuffmanNode(), HuffmanNode(r_node.r_data)) huff_node.left.number = r_node.l_data return huff_node else: huff_node = HuffmanNode(None, HuffmanNode(), HuffmanNode()) huff_node.left.number = r_node.l_data huff_node.right.number = r_node.r_data return huff_node
def generate_tree_postorder(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes that node_lst represents a tree in postorder. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in 'node_lst' @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 0, 1, 0)] >>> generate_tree_postorder(lst, 2) HuffmanNode(None, HuffmanNode(None, HuffmanNode(5, None, None), \ HuffmanNode(7, None, None)), \ HuffmanNode(None, HuffmanNode(10, None, None), HuffmanNode(12, None, None))) """ if root_index not in range(len(node_lst)): return None else: a = node_lst[root_index] g = HuffmanNode(None, None, None) if a.r_type == 0 and a.l_type == 0: g.left = HuffmanNode(a.l_data, None, None) g.right = HuffmanNode(a.r_data, None, None) if a.r_type == 0 and a.l_type == 1: g.right = HuffmanNode(a.r_data, None, None) g.left = generate_tree_postorder(node_lst, root_index - 1) if a.r_type == 1 and a.l_type == 0: a.left = HuffmanNode(a.l_data, None, None) g.right = generate_tree_postorder(node_lst, root_index - 1) if a.r_type == 1 and a.l_type == 1: g.left = generate_tree_postorder(node_lst, root_index - 2) g.right = generate_tree_postorder(node_lst, root_index - 1) return g
def generate_tree_postorder(node_lst, root_index): """Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes that the list represents a tree in postorder. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 0, 1, 0)] >>> generate_tree_postorder(lst, 2) HuffmanNode(None, HuffmanNode(None, HuffmanNode(5, None, None), \ HuffmanNode(7, None, None)), \ HuffmanNode(None, HuffmanNode(10, None, None), HuffmanNode(12, None, None))) """ tree = HuffmanNode() if len(node_lst) == 1: tree.left = HuffmanNode(node_lst[0].l_data) tree.right = HuffmanNode(node_lst[0].r_data) return tree rn = node_lst[root_index] if rn.l_type == 1: if rn.l_data == 0: tree.right = generate_tree_general([node_lst[1]], root_index) else: tree.left = generate_tree_general([node_lst[0]], root_index) else: tree.left = HuffmanNode(rn.l_data) if rn.r_type == 1: if rn.r_data == 1: tree.right = generate_tree_general([node_lst[1]], root_index) else: tree.left = generate_tree_general([node_lst[0]], root_index) else: tree.right = HuffmanNode(rn.r_data) return tree
def helper_generate_tree(node_lst): """A helper functions to generate a tree""" huffman_lst = [] for element in list(node_lst): #changing list to huffman nodes if element.l_type == 0 and element.r_type == 0: # both leaves left = HuffmanNode(element.l_data) right = HuffmanNode(element.r_data) elif (element.l_type == 0 and element.r_type == 1): # left leaf left = HuffmanNode(element.l_data) right = HuffmanNode() right.number = element.r_data elif (element.l_type == 1 and element.r_type == 0): # right leaf left = HuffmanNode() left.number = element.l_data right = HuffmanNode(element.r_data) else: # no leaves left = HuffmanNode() left.number = element.l_data right = HuffmanNode() right.number = element.r_data node = HuffmanNode(None, left, right) huffman_lst.append(node) return huffman_lst
def make_node(n, i): """ Make the elements in node_lst HuffmanNodes. """ t = HuffmanNode() if not n.l_type: t.left = HuffmanNode(n.l_data) else: t.left = HuffmanNode() t.left.number = n.l_data if not n.r_type: t.right = HuffmanNode(n.r_data) else: t.right = HuffmanNode() t.right.number = n.r_data t.number = i return t
def generate_tree_postorder(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes that the list represents a tree in postorder. Note that the parameter root_index is useless because since the tree is represented in postorder, the root node is the last element of node_lst. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12),\ ReadNode(1, 0, 1, 0)] >>> generate_tree_postorder(lst, 2) HuffmanNode(None, HuffmanNode(None, HuffmanNode(5, None, None), HuffmanNode(7, None, None)), HuffmanNode(None, HuffmanNode(10, None, None), HuffmanNode(12, None, None))) """ # we create a list of HuffmanNode nodes which are the nodes of the tree. huffman_nodes = [] root_index += 1 # since we have a postorder traversal, children are always generated before # parents. So, we go through the read nodes and transform them to internal # huffman nodes. We don't need to check if children have # already been generated, we know they were. We add the nodes to the # huffman nodes list in a postorder way, meaning that if we were to create # the list by traversing the huffman tree in postorder, we would obtain # the same list. for index, read_node in enumerate(node_lst): # create the internal node node = HuffmanNode(None, None, None) # Right child # if right child is a leaf if read_node.r_type == 0: # r_data is the symbol of the right child node.right = HuffmanNode(read_node.r_data, None, None) else: # right child is an internal leaf # index of right child is index - 1 # we know (because postorder) that it has already # been created. node.right = huffman_nodes[index - 1] # Left child # if the left child is a leaf if read_node.l_type == 0: # l_data is the symbol of the left child node.left = HuffmanNode(read_node.l_data, None, None) else: # left child is an internal leaf. We must find its index. # if right child is a leaf then left index = index - 1 if read_node.r_type == 0: # left is not leaf and right is leaf node.left = huffman_nodes[index - 1] else: # left and right both are not leafs # index of left child = index - number of internal nodes in # right child tree - 1 right_internal_nodes_count = internal_nodes_count(node.right) node.left = huffman_nodes[index - right_internal_nodes_count - 1] # Add the current node to the list of nodes huffman_nodes.append(node) # At the end, the last element in the list of nodes # is the root of the huffman tree return huffman_nodes[-1]
def generate_tree_general(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes nothing about the order of the nodes in the list. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 1, 1, 0)] >>> generate_tree_general(lst, 2) HuffmanNode(None, HuffmanNode(None, HuffmanNode(10, None, None), HuffmanNode(12, None, None)), HuffmanNode(None, HuffmanNode(5, None, None), HuffmanNode(7, None, None))) """ # root = ReadNode(1, left_node_index, 1, right_node_index) # we create a list of HuffmanNode nodes which are the nodes of the tree. # we initialize every element to None huffman_nodes = [None for _ in range(len(node_lst))] # We transform each ReadNode into an internal HuffmanNode, and we generate # the corresponding children for index, r_node in enumerate(node_lst): # enumerate(L) = [(index, L(index)] # we generate the huffman tree node whose number is index. It might have # already been generated by its parent so we check for that if huffman_nodes[index]: node = huffman_nodes[index] else: # we must generate it now node = HuffmanNode(None, None, None) # we set its number to index node.number = index # we add it to the list of huffman tree nodes, at index position huffman_nodes[index] = node # we create the left child of the node depending # on whether it's a leaf or not if r_node.l_type == 0: # it's a leaf node. l_data is the symbol if the left child child = HuffmanNode(r_node.l_data, None, None) else: # internal node, we get it from the list of # huffman nodes or we create it. # l_data is the index (and number) of the child if huffman_nodes[r_node.l_data]: child = huffman_nodes[r_node.l_data] else: # we create the left child and add it to the list child = HuffmanNode(None, None, None) child.number = r_node.l_data huffman_nodes[r_node.l_data] = child # now we set the child as a left child of the node node.left = child # we do the same thing for the right child. # we create the right child of the node # depending on whether it's a leaf or not if r_node.r_type == 0: # it's a leaf node. r_data is the symbol if the right child child = HuffmanNode(r_node.r_data, None, None) else: # it's an internal node, we get it from the # list of huffman nodes or we create it. # r_data is the index (and number) of the child if huffman_nodes[r_node.r_data]: child = huffman_nodes[r_node.r_data] else: # we create the right child and add it to the list child = HuffmanNode(None, None, None) child.number = r_node.r_data huffman_nodes[r_node.r_data] = child # now we set the child as a right child of the node node.right = child # the root node of the huffman is at root_index of the huffman_nodes list return huffman_nodes[root_index]
def generate_tree_general(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes nothing about the order of the nodes in the list. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 1, 1, 0)] >>> generate_tree_general(lst, 2) HuffmanNode(None, HuffmanNode(None, HuffmanNode(10, None, None), \ HuffmanNode(12, None, None)), \ HuffmanNode(None, HuffmanNode(5, None, None), HuffmanNode(7, None, None))) """ def generate_from_readnote(node): """Return a HuffmanNode that is generated from ReadNote @param ReadNode node: a ReadNode @rtype: HuffmanNode >>>a = ReadNode(1, 5, 0, 7) >>>b = generate_from_readnote(a) >>>b HuffmanNode(None, HuffmanNode(None, None, None), HuffmanNode(7, None, None)) """ final = HuffmanNode() if node.l_type == 0: final.left = HuffmanNode(node.l_data) elif node.l_type == 1: final.left = HuffmanNode() final.left.number = node.l_data if node.r_type == 0: final.right = HuffmanNode(node.r_data) elif node.r_type == 1: final.right = HuffmanNode() final.right.number = node.r_data return final answer_g = generate_from_readnote(node_lst[root_index]) node_lst.pop(root_index) def rebuild(lst_in, answer): """Return answer which is modified according to lst_in @param list[ReadNode] lst_in: a list of ReadNode objects @param HuffmanNode answer: a tree with only a root in it @rtype: HuffmanNode >>>list_haha = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), ReadNode(1, 1, 1, 0)] >>>root_haha = HuffmanNode(None, HuffmanNode(None, None, None), HuffmanNode(None, None, None)) >>>root_haha.left.number = 1 >>>root_haha.right.number = 0 >>>haha = rebuild(list_haha, root_haha) >>>haha HuffmanNode(None, HuffmanNode(None, HuffmanNode(10, None, None), \ HuffmanNode(12, None, None)), \ HuffmanNode(None, HuffmanNode(5, None, None), HuffmanNode(7, None, None))) """ if answer.left.number is None and answer.right.number is None: pass else: if answer.left.number is not None: answer.left = generate_from_readnote( lst_in[answer.left.number]) answer.left = rebuild(lst_in, answer.left) if answer.right.number is not None: answer.right = \ generate_from_readnote(lst_in[answer.right.number]) answer.right = rebuild(lst_in, answer.right) return answer return rebuild(node_lst, answer_g)
def generate_tree_postorder(node_lst, root_index): """ Return the root of the Huffman tree corresponding
def generate_tree_general(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes nothing about the order of the nodes in the list. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 1, 1, 0)] >>> tree_example = HuffmanNode(None, HuffmanNode(None, HuffmanNode(10, \ None, None), HuffmanNode(12, None, None)), HuffmanNode(None, \ HuffmanNode(5, None, None), HuffmanNode(7, None, None))) >>> tree_example == generate_tree_general(lst, 2) True """ if node_lst[root_index].l_type == 0 and node_lst[root_index].r_type == 0: node = HuffmanNode(None, HuffmanNode(node_lst[root_index].l_data), HuffmanNode(node_lst[root_index].r_data)) elif node_lst[root_index].l_type == 0 and node_lst[root_index].r_type == 1: node = HuffmanNode(None, HuffmanNode(node_lst[root_index].l_data), generate_tree_general(node_lst, node_lst[root_index].r_data)) elif node_lst[root_index].l_type == 1 and node_lst[root_index].r_type == 0: node = HuffmanNode(None, generate_tree_general(node_lst, node_lst[root_index].l_data), HuffmanNode(node_lst[root_index].r_data)) else: node = HuffmanNode(None, generate_tree_general(node_lst, node_lst[root_index].l_data), generate_tree_general(node_lst, node_lst[root_index].r_data)) node.number = root_index return node
"""
def generate_tree_postorder(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes that the list represents a tree in postorder. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 0, 1, 0)] >>> generate_tree_postorder(lst, 2) HuffmanNode(None, HuffmanNode(None, HuffmanNode(5, None, None), \ HuffmanNode(7, None, None)), \ HuffmanNode(None, HuffmanNode(10, None, None), HuffmanNode(12, None, None))) """ root_node_read = node_lst[root_index] root = HuffmanNode() # if the root node has two leaves. if (root_node_read.l_type, root_node_read.r_type) == (0, 0): root.left = HuffmanNode(root_node_read.l_data) root.right = HuffmanNode(root_node_read.r_data) return root else: # if root node has left leaf and right subtree. if (root_node_read.l_type, root_node_read.r_type) == (0, 1): root.left = HuffmanNode(root_node_read.l_data) root.right = generate_tree_postorder(node_lst, root_index - 1) # if root node has right leaf and left subtree. if (root_node_read.l_type, root_node_read.r_type) == (1, 0): root.left = generate_tree_postorder(node_lst, root_index - 1) root.right = HuffmanNode(root_node_read.r_data) # if both left and right have subtrees. if (root_node_read.l_type, root_node_read.r_type) == (1, 1): # construct the right subtree. root.right = generate_tree_postorder(node_lst, root_index - 1) # find the root index of the left subtree. left_root_index = root_index - count_internal(root.right) - 1 root.left = generate_tree_postorder(node_lst, left_root_index) return root
def generate_tree_postorder(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes that the list represents a tree in postorder. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 0, 1, 0)] >>> generate_tree_postorder(lst, 2) HuffmanNode(None, HuffmanNode(None, HuffmanNode(5, None, None), \ HuffmanNode(7, None, None)), \ HuffmanNode(None, HuffmanNode(10, None, None), HuffmanNode(12, None, None))) """ result = HuffmanNode() c = (root_index + 1) - (count_internal(node_lst) + 1) if node_lst[root_index].l_type == 0: if node_lst[root_index].r_type == 0: lsymbol = node_lst[root_index].l_data rsymbol = node_lst[root_index].r_data result.left = HuffmanNode(lsymbol, None, None) result.right = HuffmanNode(rsymbol, None, None) if node_lst[root_index].l_type != 0: if node_lst[root_index].r_type == 0: result.left = generate_tree_postorder(node_lst[0:-2], node_lst[root_index].l_data) rsymbol = node_lst[-2].r_data result.right = HuffmanNode(rsymbol, None, None) if node_lst[root_index].r_type != 0: if node_lst[root_index].l_type == 0: lsymbol = node_lst[0].l_data result.left = HuffmanNode(lsymbol, None, None) result.right = generate_tree_postorder(node_lst[1:-1], node_lst[root_index].r_data) if node_lst[root_index].r_type != 0: if node_lst[root_index].l_type != 0: result.right = generate_tree_postorder(node_lst[c:-1], node_lst[root_index].r_data) result.left = generate_tree_postorder(node_lst[0:c], node_lst[root_index].l_data) return result
def duplicate_node(node): """takes huffman nodes, and makes it into a single node @param HuffmanNode node: a HuffmanNode node rtype: a HuffmanNode with its left and right duplicates of itself """ return HuffmanNode(None, node.left, node.right)
def generate_tree_general(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes nothing about the order of the nodes in the list. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 1, 1, 0)] >>> a = generate_tree_general(lst, 2) >>> b = HuffmanNode(None, HuffmanNode(None, HuffmanNode(10, None, None),\ HuffmanNode(12, None, None)), HuffmanNode(None, HuffmanNode(5, None,\ None), HuffmanNode(7, None, None))) # made changes to these examples >>> a == b True """ a = HuffmanNode() if node_lst[root_index].l_type == 0 and node_lst[root_index].r_type == 0: a = HuffmanNode(None, HuffmanNode(node_lst[root_index].l_data), HuffmanNode(node_lst[root_index].r_data)) return a if node_lst[root_index].l_type == 0: a.left = HuffmanNode(node_lst[root_index].l_data) elif node_lst[root_index].l_type == 1: # can't convert to node here # because the function already returns a node a.left = generate_tree_general( node_lst, node_lst[ # recursion root_index].l_data) if node_lst[root_index].r_type == 0: # base case-ish a.right = HuffmanNode(node_lst[root_index].r_data) elif node_lst[root_index].r_type == 1: # same reason a.right = generate_tree_general( node_lst, node_lst[ # recursion root_index].r_data) return a
freq = make_freq_dict(text) tree = huffman_tree(freq) codes = get_codes(tree) number_nodes(tree) print("Bits per symbol:", avg_length(tree, freq)) result = (num_nodes_to_bytes(tree) + tree_to_bytes(tree) + size_to_bytes(len(text))) result += generate_compressed(text, codes) with open(out_file, "wb") as f2: f2.write(result) # ==================== # Functions for decompression HuffmanNode( None, HuffmanNode(101, None, None), HuffmanNode(None, HuffmanNode(115, None, None), HuffmanNode(110, None, None))) def generate_tree_general(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes nothing about the order of the nodes in node_lst. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in 'node_lst' @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 1, 1, 0)]
def create_tree(node_lst1, root_index1): """ Returns the root of the tree rooted at root_index, but this function uses n in for cases in which the tree has not been generated and we still need to create other nodes for the tree on the left. By using a list n, and continuoulsy appending -1 in each of the cases until we reach the leftmost node, we go deeper and deeper into the tree and can traverse it easily. While for the right side, if there are still nodes left to create, we send root_index - 1 for each recursion until we reach the highest leftmost node. @param list[ReadNode] node_lst1: a list of ReadNode objects @param int root_index1: index in the node list @rtype: HuffmanNode """ copy_list = node_lst1.copy() a = HuffmanNode() if node_lst1[root_index1].l_type == 0 and node_lst1[root_index1].r_type\ == 0: a = HuffmanNode(None, HuffmanNode(node_lst1[root_index1].l_data), HuffmanNode(node_lst1[root_index1].r_data)) return a if node_lst1[root_index1].l_type == 0: a.left = HuffmanNode(node_lst1[root_index1].l_data) elif node_lst1[root_index1].l_type == 1: n.append(-1) # to go deeper a.left = create_tree(copy_list, sum(n)) # sum to get int if node_lst1[root_index1].r_type == 0: # base case-ish a.right = HuffmanNode(node_lst[root_index1].r_data) elif node_lst1[root_index1].r_type == 1: # same reason # because right uppermost create_treeis always to the left of the # root in postorder a.right = create_tree(copy_list, root_index1 - 1) return a
def generate_tree_postorder(node_lst, root_index): """ Return the root of the Huffman tree corresponding to node_lst[root_index]. The function assumes that the list represents a tree in postorder. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: HuffmanNode >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 0, 1, 0)] >>> generate_tree_postorder(lst, 2) HuffmanNode(None, HuffmanNode(None, HuffmanNode(5, None, None), \ HuffmanNode(7, None, None)), \ HuffmanNode(None, HuffmanNode(10, None, None), HuffmanNode(12, None, None))) """ # todo def depth(node_lst, root_index): """ Returns the depth of each subtree. The function assumes that the list represents a tree in postorder. @param list[ReadNode] node_lst: a list of ReadNode objects @param int root_index: index in the node list @rtype: int >>> lst = [ReadNode(0, 5, 0, 7), ReadNode(0, 10, 0, 12), \ ReadNode(1, 0, 1, 0)] >>> depth(lst, 2) 2 """ root = node_lst[root_index] result = 1 i = 0 if root.r_type: i = depth(node_lst, root_index - 1) result += i if root.l_type: result += depth(node_lst, root_index - i - 1) return result root = node_lst[root_index] tree = HuffmanNode(None) if root.r_type == 0: tree.right = HuffmanNode(root.r_data) r_count = 0 else: tree.right = generate_tree_general(node_lst, root_index - 1) r_count = depth(node_lst, root_index - 1) if root.l_type == 0: tree.left = HuffmanNode(root.l_data) else: tree.left = generate_tree_general(node_lst, root_index - r_count - \ 1) return tree
l = [[2, 3], [6, 7], [3, 34], [24, 64], [1, 43]] l = sorted(l, key=getkey) print(l) """ """ Test using multiple arguements in for loop d = make_freq_dict(bytes([65, 66, 67, 66])) for k, v in d.items(): print(k, 'corresponds to', v) """ # Testing get_codes() freq = {2: 6, 3: 4, 4: 13, 5: 17} t = huffman_tree(freq) d = get_codes(t) print(t) print(d) freqs = {'a': 2} d = HuffmanNode() print(d) print(get_codes(d)) print(bytes([65, 66, 67, 66])) left = HuffmanNode(None, HuffmanNode(3), HuffmanNode(2)) right = HuffmanNode(None, HuffmanNode(9), HuffmanNode(10)) tree = HuffmanNode(None, left, right) number_nodes(tree)