Common data structure clue binary tree and Huffman tree

1. Thread Binary Tree

        In the last binary tree , we introduced the basic binary tree structure. Each parent node corresponds to two child nodes, a left child node and a right child node. Among them, we will see that the left and right nodes of many nodes are null. In order to store and traverse more efficiently, we consider a way to use these null nodes. This is the idea of ​​the clue binary tree. The left child node of null points to the predecessor node during traversal, and the right child node of null points to the subsequent node during traversal. In this way, in the process of traversal, we can directly find the predecessor and postdrive of the leaf node through the left and right child nodes, and use a line to completely string the whole tree together.

                                                                        

2. Code implementation python

          In the process of implementation, we need to add two flag bits leftType and rightType to our original Node class. They respectively indicate whether the corresponding node is a normal child node or a predecessor-posterior node. The implementation process is as follows: first we build a tree, then use the middle order to traverse the tree, and use the pre variable to record the previous node. If the left child node of the current node is null, point its left child node to the pre node; if the right child node of pre is also null, point the right child node of pre to the current node;

          Then traverse, find the bottom left child node first, if the node is a trailing node, then continue to traverse its trailing node. Otherwise, follow the normal middle order traversal to find the next node (), and keep traversing until no node is found. Then complete the traversal of the entire tree.

#-*- coding:utf-8 -*-
class Node(object):
    def __init__(self,val):
        self.val = val
        self.left = None
        self.right=None
        # 左节点类型 0表示左子节点 1表示后驱
        self.leftType = 0
        # 右节点类型 0表示右子节点 1表示后驱
        self.rightType = 0
    def show(self):
        print("遍历--当前节点为 = {}".format(self.val),end='\t')
        if self.left != None and self.leftType == 0:
            print("左子节点为 = {}".format(self.left.val),end='\t')
        if self.right != None and self.rightType == 0:
            print("右子节点为 = {}".format(self.right.val))
        if self.left != None and self.leftType == 1:
            print("前驱节点为 = {}".format(self.left.val),end='\t')
        if self.right != None and self.rightType == 1:
            print("后驱节点为 = {}".format(self.right.val))
class ThreadTree(object):
    def __init__(self):
        self.root = None
        self.pre = None
    #构建一棵基本的树
    def build(self,values):
        # 将每个元素转换为node节点
        nodes = [None if V is None else Node(V) for V in values]
        # 给根节点添加左右子节点
        for index in range(1, len(nodes)):
            parent_index = (index - 1) // 2
            parent = nodes[parent_index]
            if parent is None:
                raise Exception('parent node missing at index{}'.format(index))
            if index % 2 == 0:
                parent.right = nodes[index]
            else:
                parent.left = nodes[index]
        self.root = nodes[0]
        return nodes[0]
    #在中序遍历的过程中对每个节点中left,right为null的进行复制前驱后驱节点
    def threadedNode(self,node):
        if node == None:
            return
        self.threadedNode(node.left)
        # 处理当前节点的的前驱节点
        if node.left == None:
            node.left = self.pre
            node.leftType = 1
            print("当前节点={}".format(node.val))
            if self.pre != None:
                print("前驱结点为 = {}".format(self.pre.val))
        if self.pre != None and self.pre.right == None:
            # 前驱节点的右指针指向当前节点
            self.pre.right = node
            self.pre.rightType = 1
            print("当前节点={},后驱结点为 = {}".format(self.pre.val, node.val))
        self.pre = node
        self.threadedNode(node.right)
    def mid_order(self,node):
        while node != None:
            while node.leftType == 0:
                node = node.left
            if node != None:
                node.show()
            while node.rightType == 1:
                node = node.right
                node.show()
            node = node.right
threadTree = ThreadTree()
node = threadTree.build([1,2,3,4,5,6,7,8])
threadTree.threadedNode(node)
threadTree.mid_order(node)

3. Summary of clue binary tree

          This article introduces the principle of the clue binary tree and the process of implementing it with python. The core idea is to use the null pointers in the binary tree to make these pointers point to the pre- and post-drive nodes.

4. Huffman tree

          Disclaimer: This blog refers to the Huffman tree and its python implementation . Huffman tree is also called optimal tree and optimal binary tree. The best embodiment is to minimize the weighted path sum of all nodes. As shown in the figure, we see that in addition to the value, each node has its own weight information. The node traversed by one node to another node is called a path. For example, from the root node to c, it needs to pass 50, 29, 14, 6; the length of the weighted path is defined as follows: the weight is multiplied by the number of corresponding paths, For example, the weighted path length WPL in the figure below is: 9*2+12*2+15*2+6*3+3*4+5*4 = 122. Our goal is to minimize the length of the weighted path. In fact, the greater the weight, the closer to the root node, so as to ensure that the overall weighted sum is the smallest.

                                         

          Next, we introduce the algorithm implemented: sort the weight list, each time the two nodes with the smallest weight are selected as the left and right child nodes to generate a tree, and the sum of their weights is used as the root node of the tree. The two leaf nodes are deleted from the weight list, and the weight of the root node is added to the weight list. Continue to iterate the above process until there is only one root node, and the whole tree generation ends.

                           

   Huffman coding: The Huffman tree has the shortest weighted path length, and the path from each node to the root node is unique, so it can be used for coding. This is a unequal length encoding method, which saves space to a large extent.

           We count where each word appears in the text, as its weight, construct a Huffman tree, and specify that the left branch path of each subtree is 0 and the right branch path is 1. In this way, the path corresponding to the node is found, and it can be encoded along the path. For example, the following a can be coded as 00, and b can be coded as 01;

                                      

5.Python code implementation

#-*- coding:utf-8 -*-
#节点类
class Node(object):
    def __init__(self,name=None,value=None):
        self._name=name
        self._value=value
        self._left=None
        self._right=None

#哈夫曼树类
class HuffmanTree(object):

    #根据Huffman树的思想:以叶子节点为基础,反向建立Huffman树
    def __init__(self,char_weights):
        #将字典中所有的值 变成node数组
        self.a=[Node(part[0],part[1]) for part in char_weights]  #根据输入的字符及其频数生成叶子节点
        while len(self.a)!=1:
            #每次取权重最小的两个节点 生成父节点
            #这两个节点分别为左右节点
            self.a.sort(key=lambda node:node._value,reverse=True)
            c=Node(value=(self.a[-1]._value+self.a[-2]._value))
            c._left=self.a.pop()
            c._right=self.a.pop()
            self.a.append(c)
        self.root=self.a[0]
        self.b=list(range(10))          #self.b用于保存每个叶子节点的Haffuman编码,range的值只需要不小于树的深度就行

    #用递归的思想生成编码
    def huffmanEncode(self,tree,length):
        node=tree
        if (not node):
            return
        elif node._name:
            print(node._name + '的编码为:',end='\t')
            for i in range(length):
                print(self.b[i],end='\t')
            print ('\n')
            return
        self.b[length]=0
        self.huffmanEncode(node._left,length+1)
        self.b[length]=1
        self.huffmanEncode(node._right,length+1)
     #生成哈夫曼编码
    def get_code(self):
        self.huffmanEncode(self.root,0)

if __name__=='__main__':
    #输入的是字符及其频数
    char_weights=[('a',5),('b',4),('c',10),('d',8),('f',15),('g',2)]
    tree=HuffmanTree(char_weights)
    tree.get_code()

6. Huffman tree summary

         Above we introduced the Huffman tree, also known as the optimal binary tree. The basic idea is to minimize the sum of weighted paths, that is, the node with the greater weight is closer to the root node. The idea of ​​implementing the algorithm is to select two nodes with the smallest weights from the weight list each time as the left and right nodes, and the sum of them as the root node constitutes a tree. Then delete these two nodes from the weight list and add their sum. Iterate until there is only one root node. Then we introduced one of the practical applications of Huffman trees, Huffman coding. It is specified that the left branch is 0 and the right branch is 1, and codes are generated through the values ​​of all branches on the path of the node. This is a coding method that has unequal lengths, but can guarantee the uniqueness of nodes. Greatly saves space.

7. Gossip

           I can keep this heaven, and I can kill it! I stayed up for three days and two nights, and finally finished watching Liuli. After reading it, I feel very sad, just like being broken in love. I really like Miss Yuan Bingyan so much, that kind of cute smile is no second in the world. Please allow me to borrow a few poems from "Luo Shen Fu" to express my admiration for my little sister: Pianruo Jinghong, graceful as a dragon. Rong Yao Qiuju, Huamao Chunsong. It seems as if the moon is covered by light clouds, and the breeze is like snow returning to the wind. Who can let me see her, you are my greatest benefactor in my life. The bad news today is that the goddess I like for four and a half years is married. Ugh! Of course it will be very sad. But what does this show? It's just that during this period of time I need to use a lot of other things to fill my thoughts and avoid one person thinking too much and leaving too many tears! It's just that she didn't belong to me in the short few decades of her life. If you think about it this way, you feel that life is still going on. I never expect anything from others. Now I am only looking forward to Miss Bingyan’s next TV series.

Liuli·God of War-I once carried the delusion of all living beings-Burning abuse

 

Guess you like

Origin blog.csdn.net/gaobing1993/article/details/108902921