• 哈弗曼树的建立、编码与部分代码解释


    今天就来回顾一下二叉树,其实在大二上专业课的时候就做过一次哈弗曼树的编码了,这次只做简单的复习,因此忽略掉其中对文本的转换,只实现了哈弗曼树的构建和节点编码。

    在哈弗曼树构建的过程中,一个很重要的点就是这个树的规模到底有多大。
    对于完全二叉树有性质:

    [n0 = n2+1; ]

    其中n0指的是叶子节点,即儿子节点的个数为0,n2指的是有两个儿子节点的节点。

    而对于哈弗曼树,它是由每两个节点得到一个新节点逐渐构建而成的,因此只有节点数为0或者为2的节点,而且我们需要编码的字符一定都是叶子节点。因此,如果我们需要编码的字符有n个,即叶子节点的个数n0=n,我们可以推得:

    [egin{align} &n0 + n1 + n2 \ &= n + 0 + n - 1 \&= 2 * n -1; end{align} ]

    因此我们可以知道我们要开的存放树的节点空间要多大。

    字符编码的时候要注意主要思想是从叶子节点往根节点走,因此我们在设计结构体的时候需要有存放parent的下标的变量。这样子在查找编码的过程中,只需要从叶子节点开始,走到根节点即可。

    其他的不详细解释,大概的流程是:

    • 先对所有的元素做初始化,动态数组中的前n个元素存放着我们需要编码的字符及对应信息,因此可以先对这些节点的weight或者data赋值。
    • 动态数组中n+1到2n-1的元素就是我们在哈弗曼树构建过程中新增的节点
    • 找到数据中的前两个权重最小的元素,并创建一个新的节点,对这个节点赋值
    • 字符编码

    具体实现代码如下:

    
    #include<iostream>
    #include<vector>
    #include<string>
    #define M 65535
    using namespace std;
    
    typedef struct HuffTreeNode{
        int left;
        int right;
        int weight;
        int parent;
    
    }HuffTreeNode, *HuffTreeP;
    
    typedef struct HuffTreeCode{
    
        int data;
        char* code;
    
    }HuffTreeCode, *HuffTreeCodeP;
    
    
    void buildTree(HuffTreeP & HuffTree, int n){
        int m , t, i;
        //int arr[7] = {1,2,4,5,6,7,9};
      
         //n0 = n, 共有2n-1个节点
        m = 2 * n - 1;
        HuffTree  = (HuffTreeP)malloc((2 * n - 1)* sizeof(HuffTreeNode));
        // init leaf node
    
        for(i = 0; i < n; i++){
            cin >> t;
            //t = arr[i];
            HuffTree[i].parent = -1;
            HuffTree[i].right = -1;
            HuffTree[i].left = -1;
            HuffTree[i].weight = t;
        }
        // init other nodes
        for(i = n; i < m; i++){
            HuffTree[i].parent = -1;
            HuffTree[i].right = -1;
            HuffTree[i].left = -1;
            HuffTree[i].weight = M;
        }
    
        int min1, min2 , index1 = -1, index2 = -1;
        for(int i = n; i < m; i++){
            //find two biggest value
            min1 = M;
            min2 = min1;
            for(int j = 0; j < m ; j++){
    
                if(HuffTree[j].parent != -1){
                    continue;
                }
                if(HuffTree[j].weight <= min1 && HuffTree[j].weight < min2){
                    min2 = min1;
                    min1 = HuffTree[j].weight;
                    index2 = index1;
                    index1 = j;
                    
                }else if(HuffTree[j].weight >= min1 && HuffTree[j].weight < min2){
                    min2 = HuffTree[j].weight;
                    index2 = j;
       
                }
    
            }
    
            //构建这两个子节点的父节点
            HuffTree[index1].parent = i;
            HuffTree[index2].parent = i;
            HuffTree[i].left = index1;
            HuffTree[i].right = index2;
            HuffTree[i].weight = min1 + min2;
    
            cout << "min1=" << min1 << " min2=" << min2 << endl;
            
        }
    
    
    }
    
    void reverse(char* & s, int m){
    
        char* sTemp = (char * )malloc((m+1) * sizeof(char));
        int i = 0;
        cout << "s=" << s << endl;
        while(m >= 0){
            sTemp[i++] = s[m--];
        }
        s = sTemp;
    }
    
    void encode(HuffTreeP HuffTree, HuffTreeCodeP & codeTree, int n){
        //parent = -1为根节点
        codeTree = (HuffTreeCodeP)malloc(n* sizeof(HuffTreeCode));
        char * s = (char*)malloc((n+1) * sizeof(char));
        //string s = "";
        int j = 0, p = 0, m = 0;
        for(int i = 0; i < n; i++){
            m = 0;
            j = i;
            while(j < 2 * n - 2){
                p = HuffTree[j].parent;
                
                if(HuffTree[p].left == j){
                    s[m]= '0';
                }else{
                    s[m]= '1';
                }
                j = p;
                m++;
            
            }
                    cout << "data=" << codeTree[i].data << " code=" << s << endl;
            reverse(s, m);
            codeTree[i].code = s;
            codeTree[i].data = HuffTree[i].weight;
    
        }
    
    }
    
    void printCode(HuffTreeCodeP codeTree, int n){
        for(int i = 0; i < n; i++){
            cout << "data: " << codeTree[i].data << " code: " << codeTree[i].code << endl;
        }
    
    }
    
    int main()
    {
        int n;
        cin >> n;
    // n = 7;
        HuffTreeP HuffTree;
        HuffTreeCodeP codeTree;
        buildTree(HuffTree, n);
        encode(HuffTree, codeTree, n);
        printCode(codeTree, n);
        
    }
    
    
  • 相关阅读:
    IIS调试技术之 Debug Diagnostic (调试诊断)
    其实,你什么都不用怕
    应用程序出现挂死,.NET Runtime at IP 791F7E06 (79140000) with exit code 80131506.
    LR_问题_如何将场景中的用户设置为百分比形式
    LR_问题_脚本运行时提示没有参数化
    LR_问题_无法打开IE浏览器、监视服务器资源
    LR_问题_运行场景时提示scripts you are running in invalid
    收集好用的在线调试工具
    es2015 解构赋值
    shim和polyfill
  • 原文地址:https://www.cnblogs.com/yuyuan-bb/p/12602642.html
Copyright © 2020-2023  润新知