赫夫曼树和赫夫曼编码

什么是哈夫曼树

当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,有时也叫“赫夫曼树”或者“哈夫曼树”。

在构建哈弗曼树时,要使树的带权路径长度最小,只需要遵循一个原则,那就是:权重越大的结点离树根越近。在图 1 中,因为结点 a 的权值最大,所以理应直接作为根结点的孩子结点。

    

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
#include<limits.h>
typedef struct{
    unsigned int weight;
    unsigned int parent,lchild,rchild;
}htnode,*huffmantree;  // 赫夫曼树的结构类型

typedef char **huffmancode;

int min(huffmantree t, int i){
    int j,flag;
    unsigned int k=UINT_MAX;
    for(j=1;j<=i;j++){
        if(t[j].weight<k&&t[j].parent==0){
        k=t[j].weight;  flag=j;
        }
    }
        t[flag].parent=1;
        return flag;
}
void select(huffmantree t,int i,int &s1,int &s2){
    int j;
    s1=min(t,i);
    s2=min(t,i);
    if(s1>s2){
    j=s1;  s1=s2;  s2=j;
    }
}
void huffmancoding(huffmantree &ht,huffmancode &hc,int *w,int n){
    int m,i,s1,s2,start;
    unsigned int c,f;
    huffmantree p;
    char *cd=NULL;

    m=2*n-1;
    ht=(huffmantree)malloc((m+1)*sizeof(htnode));  // m+1表示0号单元不用
    for(p=ht+1,i=1;i<=n;i++,p++){
        p->weight=w[i-1];  p->parent=0; p->lchild=0; p->rchild=0;
    }
    for(;i<=m;i++,p++){
        p->parent=0;
    }
    for(i=n+1;i<=m;i++){   //建立赫夫曼树
        select(ht,i-1,s1,s2);
        ht[s1].parent=ht[s2].parent=i;
        ht[i].lchild=s1;  ht[i].rchild=s2;
        ht[i].weight=ht[s1].weight+ht[s2].weight;
    }

    hc=(huffmancode)malloc((n+1)*sizeof(char *));
    cd=(char *)malloc(n*sizeof(char));  //用来存储每个字符的编码
    cd[n-1]=‘\0‘;   //编码结束符
    for(i=1;i<=n;i++){
        start=n-1;
        for(c=i,f=ht[i].parent;f!=0;c=f,f=ht[f].parent){
         // 一直循环知道最后一个没有双亲的结点,用f来寻找父母往上走
            if(ht[f].lchild==c)  cd[--start]=‘0‘;
            else   cd[--start]=‘1‘; //这里分支语句用来判断在左还是右,编码0和1
        }    //n-1位置已经存放了‘/0‘,所以用--start,从n-2存放0,1编码
        hc[i]=(char *)malloc((n-start)*sizeof(char));
        strcpy(hc[i],&cd[start]);
    }
    free(cd);
}

int main(){
    huffmantree ht=NULL;  // 二级指针
    huffmancode hc;
    int *w,n,i;
    printf("Please input the number of all the node digit:");
    scanf("%d",&n);
    w=(int *)malloc(n*sizeof(int));
    printf("Please input the %d node digits:\n",n);
    for(i=0;i<n;i++){
    scanf("%d",w+i);
    }
    huffmancoding(ht,hc,w,n);
    for(i=1;i<=n;i++){
    puts(hc[i]);}
    getch();

}

原文地址:https://www.cnblogs.com/xiaoqiz/p/10847191.html

时间: 2024-11-05 14:58:24

赫夫曼树和赫夫曼编码的相关文章

使用优先队列构建赫夫曼树

关于赫夫曼编码和赫夫曼树的相关知识可参考之前两篇文章(由二叉树构造赫夫曼树.赫夫曼编码).本文介绍另一种构建赫夫曼树的方式,采用优先队列. 步骤: 1.首先我们需要统计不同字符出现的次数.一个字符出现的次数越多,说明其优先级越高,其赫夫曼编码应该越短: 2.将待编码的字符(即带权节点)存入优先级队列,优先级即字符出现的次数: 3.不断迭代队列,直到队列中剩下一个元素(即根节点).每次从队列中取出两个优先级最小的元素(优先级队列中的元素是按照节点优先级顺序排列的),然后生成一个新的赫夫曼树节点,节

javascript实现数据结构: 树和二叉树的应用--最优二叉树(赫夫曼树),回溯法与树的遍历--求集合幂集及八皇后问题

赫夫曼树及其应用 赫夫曼(Huffman)树又称最优树,是一类带权路径长度最短的树,有着广泛的应用. 最优二叉树(Huffman树) 1 基本概念 ① 结点路径:从树中一个结点到另一个结点的之间的分支构成这两个结点之间的路径. ② 路径长度:结点路径上的分支数目称为路径长度. ③ 树的路径长度:从树根到每一个结点的路径长度之和. 以下图为例: A到F :结点路径 AEF : 路径长度(即边的数目) 2 : 树的路径长度:3*1+5*2+2*3=19: ④ 结点的带权路径长度:从该结点的到树的根结

赫夫曼树JAVA实现及分析

一,介绍 1)构造赫夫曼树的算法是一个贪心算法,贪心的地方在于:总是选取当前频率(权值)最低的两个结点来进行合并,构造新结点. 2)使用最小堆来选取频率最小的节点,有助于提高算法效率,因为要选频率最低的,要么用排序,要么用堆.用堆的话,出堆的复杂度为O(logN),而向堆中插入一个元素的平均时间复杂度为O(1),在构建赫夫曼树的过程中,新生成的结点需要插入到原来的队列中,故用堆来维持这种顺序比排序算法要高效地多. 二,赫夫曼算法分析 ①用到的数据结构分析 首先需要构造一棵赫夫曼树,因此需要二叉链

13.赫夫曼树及其应用

一.赫夫曼树定义与原理 1.路径长度:从树中一个结点到另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目称作路径的长度; 2.树的路径长度:即从树根到每一结点的路径长度之和; 3.结点的带权的路径长度:即从该结点从到树根之间的路径长度与结点上权的乘积; 4.树的带权路径长度:为树中所有叶子结点的带权路径长度之和; 5.赫夫曼树定义:假设有n个权值{w1,w2,....,wn},构造一颗有n个叶子结点的二叉树,每个叶子结点带权wk,每个叶子的路径长度为lk,则其中带权路径长度WPL最小的

【数据结构】赫夫曼树的实现和模拟压缩(C++)

赫夫曼(Huffman)树,由发明它的人物命名,又称最优树,是一类带权路径最短的二叉树,主要用于数据压缩传输. 赫夫曼树的构造过程相对比较简单,要理解赫夫曼数,要先了解赫夫曼编码. 对一组出现频率不同的字符进行01编码,如果设计等长的编码方法,不会出现混淆的方法,根据规定长度的编码进行翻译,有且只有一个字符与之对应.比如设计两位编码的方法,A,B,C,D字符可以用00-11来表示,接收方只要依次取两位编码进行翻译就可以得出原数据,但如果原数据只由n个A组成的,那发出的编码就是2n个0组成,这样的

基础数据结构-二叉树-赫夫曼树的解码(详解)

本篇是上一篇赫夫曼树构建与编码的后续,稍微详细讲一下解码的算法. Huffman解码算法流程: 1.定义指针p指向赫夫曼树结点,实际是记录结点数组的下标: 2.定义指针i指向编码串,定义ch逐个取编码串的字符: 3.初始化:读入编码串,设置p指向根结点,i为0: 4.执行以下循环: a)取编码串的第i个字符放入ch: b)如果ch是字符0,表示往左孩子移动,则p跳转到右孩子: c)如果ch是字符1,表示往右孩子移动,则p跳转到右孩子: d)如果ch非0非1,表示编码串有错误,输出error表示解

赫夫曼树的构建、编码、译码解析

当你開始看这篇博文的时候.我相信你对树及二叉树的基本概念已有所了解.我在这里就不再赘述. 我们主要对赫 夫曼树的特点.构建.编码.译码做一个具体的介绍,并附有代码,全部函数代码都通过了測试.我不保证全部代码是最优的(毕竟是我一个人苦思冥想出来的,我相信在大家的集思广益之下还有优化的空间),但我保证全部代码是正确的. 一.赫夫曼树的特点 赫夫曼树又称作最优二叉树,是一类带权路径长度最短的树. 首先给出路径和路径长度的概念.从树中一个节点到 还有一个节点之间的分支构成这两个节点之间的路径.路径上的分

《大话数据结构》笔记(6-3)--树:赫夫曼树

代码实现: 第六章    树:赫夫曼树 赫夫曼树定义与原理 从树中一个结点到另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目称作路径长度. 树的路径长度就是从树根到每一结点的路径长度之和. 对于带权的结点,结点的带权路径长度为从该结点到树根之间的路径长度与结点上权的乘积. 树的带权路径长度为树中所有叶子结点的带权路径长度之和. 假设有n个权值{w1, w2, ..., wn},构造一棵有n个叶子结点的二叉树,每个叶子结点带权wk ,每个叶子的路径长度为lk,则其中带权路径长度WPL最

经典算法题每日演练——第十三题 赫夫曼树

原文:经典算法题每日演练--第十三题 赫夫曼树 赫夫曼树又称最优二叉树,也就是带权路径最短的树,对于赫夫曼树,我想大家对它是非常的熟悉,也知道它的应用场景, 但是有没有自己亲手写过,这个我就不清楚了,不管以前写没写,这一篇我们来玩一把. 一:概念 赫夫曼树里面有几个概念,也是非常简单的,先来看下面的图: 1. 基础概念 <1>  节点的权: 节点中红色部分就是权,在实际应用中,我们用“字符”出现的次数作为权. <2>  路径长度:可以理解成该节点到根节点的层数,比如:“A”到根节点