class HuffmanNode:
    # $ will represent a dummy node
    # anything  else  is a regular node
    def __init__(self, data, freq):
        self.data = data
        self.freq = freq


class HuffmanTree:
    def __init__(self, node):
        self.root = node

    def frequencyMap(self, string):
        ret = {}
        for i in string:
            if i not in ret:
                ret[i] = Node(i, 1)
            else:
                ret[i].freq += 1

        return ret


    def encode(self, string):
        f = self.frequencyMap(string)

class TrieNode:
    def __init__(self):
        # 1 ref for each character in the alphabet
        self.isleaf = False
        self.edges = [0] * 26

class TrieTree:
    def __init__(self, root):
        self.root = root

    # just not going to bother with capitals
    def _charIndex(self, char):
        return ord(char) - ord('a')

    def insert(self, string):
        curr = self.root
        for i in string:
            alphabetIndex = _charIndex(i)
            if curr[alphabetIndex] is None:
                curr.edges[alphabetIndex] = Node()
            # go to the nexxt thing
            curr = curr.edges[alphabetIndex]
        else:
            # Finally mark the last node as a leaf
            curr.isleaf = True

    def lookup(self, string):
        curr = self.root
        # First we should go straight to the end of the string
        # That's why we don't do any checks
        for i in string:
            alphaIndex = _charIndex(i)
            curr = curr.edges[alphaIndex]

        return curr.isleaf

    def remove(self, string):
        pass

    def traverse(self, node, preFix):
        if node:
            if n.isleaf:
                print(prefix)
            # recursively go through the tree
            for i in prefix:
                traverse(node.edges[_i], prefix+_charIndex(i))

class AVLNode:
    def __init__(self, data):
        self.data = data
        self.height = 0
        self.left = None
        self.Right = None

class AVLTree:
    def __init__(self,node):
        self.root = node
    
    def rotateLeft(self, node):
        tmp = node.right
        node.left = tmp.right
        tmp.right = node

        # Set the heights on each node
        node.height = 1 + max(node.left.height, node.right.height)
        tmp.height = 1 + max(tmp.left.height, tmp.right.height)
        return tmp

    def rotateRight(self, node):
        pass
