zoukankan      html  css  js  c++  java
  • 哈夫曼树及其编码

    首先是哈夫曼树的定义:在一棵二叉树中,带权路径长度达到最小,成这样的树是最优二叉树,也是哈弗曼树。大概意思就是把数值大的节点放在树上面,数值小的节点放在树下面。哈夫曼树的结构使用顺序结构,这里直接使用了数组。

    建造哈弗曼树的思路:根据二叉树的性质,有n个叶子节点,二叉树就会有2n-1个节点。定义一个数组,前n个节点作为叶子节点,从前n个节点中选择两个最小的节点,作为一棵二叉树的左右节点,这棵二叉树的根节点值为左右孩子节点值之和。把这个根节点的值放入数组中,然后接着从数组中(新加入的节点也算)选取两个最小的节点,只不过把已经使用过的节点忽略掉,这样不断循环,每个节点和其他节点都有对应关系。

    代码实现:

    定义结构体,里面有四个成员,分别为权值,父节点,左孩子节点,右孩子节点,这里的节点指的是他在数组中对应的下标位置,如果是0则没有父节点或者孩子节点,权值不能为0.

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #define n 7
     5 #define m 2*n-1
     6 #define maxval 100
     7 
     8 typedef struct{
     9     int weight;
    10     int parent,lchild,rchild;
    11 }HufmTree;
    12 
    13 HufmTree *init(){
    14     
    15     HufmTree *hf = (HufmTree *)malloc(sizeof(HufmTree));
    16     if(hf==NULL)
    17         return NULL;
    18     
    19     return hf;
    20     
    21 }
    22 
    23 void setHuffmanTree(HufmTree *tree[]){
    24     
    25     int i,j,p1,p2,s1,s2;
    26     for(i=n;i<m;i++){                        //从n位置开始,都是两个节点新合成的节点,直到m位置结束 
    27         p1 = p2 = 0;                         //每次循环开始,都要数组从头开始遍历 
    28         s1 = s2 = maxval;                    
    29         for(j=0;j<=i-1;j++)                    //在所有节点中寻找,i后面没有数值的空位置用不到 
    30             if(tree[j]->parent==0)             //此处的代码的作用是检查该节点是否已经使用过,因为使用过的节点肯定有父节点    
    31                 if(tree[j]->weight<s1){        //寻找最小权值的节点 
    32                     s2 = s1;                    
    33                     s1 = tree[j]->weight;
    34                     p2 = p1;
    35                     p1 = j;
    36                 }
    37                 else if(tree[j]->weight<s2){//寻找次小权值的节点 
    38                     s2 = tree[j]->weight;
    39                     p2 = j;
    40                 }
    41         tree[p1]->parent = tree[p2]->parent = i;    //把两个最小节点的父节点指向i 
    42         tree[i]->weight = tree[p1]->weight + tree[p2]->weight;    //父节点权值等于左右孩子权值之和 
    43         tree[i]->lchild = p1;                //指明父节点的左右孩子节点 
    44         tree[i]->rchild = p2;
    45     }
    46     
    47 }
    48 
    49 void display(HufmTree *tree[n]){
    50     
    51     int i;
    52     for(i=0;i<m;i++){
    53         printf("%d ",tree[i]->weight);
    54     }
    55     printf("
    ");
    56 }

    哈弗曼编码:使出现频率高的编码放在上面,频率低的编码放在下面。

     

    以上图为例,其中A的频率最高,离根节点最近,GFED频率最低,在最下面。

    实现原理:从根节点到每个叶子节点间的路径值作为编码,图片里的规定是左子树的路径为1,右子树的路径为0,这样每个节点都有自己的编码且不会重复

     1 void createHuffmanCode(HufmTree *tree[n]){
     2      
     3      
     4      int i,j,p,start;
     5      char *temp;                                    //临时存放字母编码的数组 
     6      for(i=0;i<n;i++){                            //从0~n之间都是二叉树的叶子节点 
     7          start = n-1;                            //存放temp数组的下标,从后往前,指向最后面 
     8          temp = (char *)malloc(n*sizeof(char));    //为数组分配空间 
     9         temp[start] = '';                        //添加字符串结束标志 
    10          j = i;                                    //j代表为哪个叶子节点编码 
    11         p = tree[j]->parent;                    //p是j的父节点 
    12          while(p!=0){
    13              if(tree[p]->lchild==j)
    14                  temp[--start] = '0';            //如果j是p的左孩子,则在数组中添加一个 '0'
    15             else
    16                 temp[--start] = '1';            //反之则添加一个 '1'
    17             j = p;
    18             p = tree[p]->parent;                //j和p不断往上循环 
    19         }
    20         printf("%d:%s 
    ",tree[i]->weight,&temp[start]);
    21     }
    22      
    23  }
    24  
    25 void main(){
    26     
    27     HufmTree *tree[m];
    28     int i,num[n] = {7,3,2,4,9,10,5};
    29     
    30     //分配空间 
    31     for(i=0;i<m;i++)
    32         tree[i] = init();
    33         
    34     //数组每个节点内的所有值初始化时都设为0 
    35     for(i=0;i<m;i++){
    36         tree[i]->weight = 0;
    37         tree[i]->parent = 0;
    38         tree[i]->rchild = 0;
    39         tree[i]->lchild = 0;
    40     }
    41     
    42     //为数组前n个数的权值赋值 
    43     for(i=0;i<n;i++)
    44         tree[i]->weight = num[i];
    45     
    46     setHuffmanTree(tree);
    47     
    48     display(tree);
    49     
    50     createHuffmanCode(tree);
    51     
    52 }
  • 相关阅读:
    禁止使用U盘和移动硬盘
    Linux下Red5安装和配置
    ORACLE 10g下载地址
    常挂在美国人嘴边的最酷口语
    关于oracle中spfile和pfile的一个实验
    nginx搭建流媒体服务器
    powerDesigner 把name项添加到注释(comment),完美方案!
    memcached全面剖析–PDF总结篇
    PD 导出SQL语句
    本地读取虚拟机系统中的资源
  • 原文地址:https://www.cnblogs.com/lsy-lsy/p/11917127.html
Copyright © 2011-2022 走看看