数据结构--哈夫曼树

哈夫曼算法

构造哈夫曼树的方法

  • 1.根据n个给定权值{w1, w2, ..., wn}构成n棵二叉树的森林F = {T1, T2, ..., Tn}, 其中Ti只有一个带权为wi的根结点。

  • 2.在F中选取两棵根结点的权值最小的树作为左右子树,构造一棵新的二叉树,且设置新的二叉树的根结点的权值为其左右子树上的根结点的权值之和。

  • 3.在F中删除这两棵树,同时将新得到的二叉树加入森林中。

  • 4.重复2.和3.直到森林中只有一棵树为止,这棵树就是哈夫曼树

性质

  • 哈夫曼树的节点的度数为0 或 2,没有度为1的节点
  • 包含n个叶子节点的哈夫曼树中共有2n-1个节点
  • 包含n棵树的森林要经过n-1次合并才能形成n-1个新节点

哈夫曼树的存储结构

  • 顺序存储结构

    使用一维结构数组存储,数组元素定义如下:

typedef struct{
  int weight; //节点的权重
  int parent, lch, rch; //父节点,左右孩子节点的下标
}HTNode, *HuffmanTree
    删除节点的方式:更新节点的父节点,及其父节点的左右孩子节点。遍历节点时,要从父节点值不为零的节点中选取。当数组中只有一个节点的父节点值为0时结束。

哈夫曼编码

要设计长度不等的编码,则必须使任意字符的编码都不是另一字符的编码的前缀——前缀编码

  • 统计字符集中每个字符的平均出现频率。
  • 以概率值作为权值构造哈夫曼树,概率越大的节点,路径越短。
  • 在哈夫曼树的分枝上标上0 或 1:节点的左分支标0,右分支标1,把从根到每个叶子的路径上的标号连接起来,作为该叶子代表的字符的编码。

1. 为什么哈夫曼编码能够保证是前缀编码?

因为没有一片树叶是另一片树叶的祖先,所以每个叶节点的编码就不可能是其他叶节点编码的前缀。

2. 为什么哈夫曼编码能够保证字符编码总长度最短?

因为哈夫曼树的带权路径长度最短,故字符编码的总长度最短。

  • 哈夫曼编码是前缀码且是最优前缀码

3.解码的方法

  • 构造哈夫曼树
  • 依次读入二进制码
  • 读入0,则走向左孩子;读入1,则走向右孩子
  • 一旦到达某叶子节点时,可译出字符
  • 然后再从根出发继续译码,直到结束

C语言实现

构造哈夫曼树

void CreateHuffmanTree(HuffmanTree* HT, int n, int* weights){
    if(n <= 1)return;
    *HT = (HuffmanTree)malloc(sizeof(struct HTNode)*(2*n-1));
    HuffmanTree P = *HT;
    for(int i = 0; i < 2*n-1; i++){
        (P+i)->lch = -1;
        (P+i)->rch = -1;
        (P+i)->parent = -1;
    }
    for(int i = 0; i < n; i++){
        (P+i)->weight = weights[i];
    }
    int min_idx = 0, nmin_idx = 0;
    for(int i = n; i < 2*n-1; i++){
        Select(HT, &min_idx, &nmin_idx, i);
        (P+i)->lch = min_idx;
        (P+i)->rch = nmin_idx;
        (P+i)->weight = (P+min_idx)->weight + (P+nmin_idx)->weight;
        (P+min_idx)->parent = i;
        (P+nmin_idx)->parent = i;
    }
}

构建哈夫曼编码

char** CreateHuffmanCode(HuffmanTree* HT, int n){
    char** HC = malloc(sizeof(char*)*(n));
    char* cd = (char*)malloc(sizeof(char)*n);
    cd[n-1] = '\0';
    HuffmanTree P = *HT;
    for(int i = 0; i < n; i++){
        int start = n-1, c = i, f = (P+i)->parent;
        while(f != -1){
            start--;
            if((P+f)->lch == c)cd[start] = '0';
            else cd[start] = '1';
            c = f;
            f = (P+f)->parent;
        }
        HC[i] = (char*)malloc(sizeof(char)*(n-start));
        strcpy(HC[i], &cd[start]);
    }
    free(cd);
    return HC;
}
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容

  • 一、 一些基本概念1、 路径长度树中一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上的分支数目为...
    Qi0907阅读 2,574评论 0 1
  • 哈夫曼树 1.1基本介绍 给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称...
    smallmartial阅读 1,703评论 0 0
  • 这篇文章收录在我的 Github 上 algorithms-tutorial,另外记录了些算法题解,感兴趣的可以看...
    Lindz阅读 8,795评论 1 6
  • 哈夫曼编码(Huffman Coding) ? 哈夫曼编码,又称为霍夫曼编码,它是现代压缩算法的基础? 假设要把字...
    鼬殿阅读 330评论 0 2
  • 好,前面我们介绍了一般二叉树、完全二叉树、满二叉树,这篇文章呢,我们要介绍的是哈夫曼树。哈夫曼树也叫最优二叉树,与...
    绿萝呀阅读 1,364评论 0 1