zoukankan      html  css  js  c++  java
  • 哈夫曼编码_静态库

    
    
    #include <stdio.h>
    #include <string.h>
    #define N 50        //叶子结点数
    #define M 2*N-1        //树中结点总数
    typedef struct//哈夫曼树的节点
    {
        char data[5];    //结点存储的单词
        int weight;        //权重(该单词出现次数)
        int parent;        //双亲结点
        int lchild;        //左孩子结点
        int rchild;        //右孩子结点
    } HTNode;
    typedef struct//哈夫曼编码
    {
        char cd[N];    //叶子节点对应的哈夫曼编码
        int start; //指向哈夫曼编码cd[]的最开始字符(从下标start开始到n为有效的哈夫曼编码)
    } HCode;
    
    void CreateHT(HTNode ht[],int n);//构造
    void CreateHCode(HTNode ht[],HCode hcd[],int n);//编码
    void DispHCode(HTNode ht[],HCode hcd[],int n);//输出编码
    void main()
    {
        int n=15;//15个单词(叶节点)
        ////初始化
        char *str[]={"The","of","a","to","and","in","that","he","is","at","on","for","His","are","be"};
        int fnum[]={1192,677,541,518,462,450,242,195,190,181,174,157,138,124,123};
        HTNode ht[M];//节点
        HCode hcd[N];//编码
        for (int i=0;i<n;i++)
        {
            strcpy(ht[i].data,str[i]);
            ht[i].weight=fnum[i];
        }
        CreateHT(ht,n);//构造哈夫曼树
        CreateHCode(ht,hcd,n);//根据哈夫曼树建立哈夫曼编码
        DispHCode(ht,hcd,n);//输出哈夫曼编码
        printf("\n");
    }
    
    
    void CreateHT(HTNode ht[],int n)
    {
        int i,k,lnode,rnode;
        int min1,min2;
        for (i=0;i<2*n-1;i++)//ht[]初始化---所有结点的相关域置初值-1
            ht[i].parent=ht[i].lchild=ht[i].rchild=-1;
        //构造哈夫曼树///////////////////////////////
        for (i=n;i<2*n-1;i++)
        {
            min1=min2=32767;//最小权重和次小权重
            lnode=rnode=-1;//最小两个权重位置(节点下标)
            //从已有的节点且未构造二叉树的节点中选取权重最小的两个节点
            for (k=0;k<=i-1;k++)//树中现有i个节点
                if (ht[k].parent==-1)//尚未构造二叉树的结点
                {
                    if (ht[k].weight<min1)//k号节点权重比最小权重min1还小
                    {
                        min2=min1;rnode=lnode;//次小权重min2取最小权重min1
                        min1=ht[k].weight;lnode=k;//最小权重min1取k号节点对应的权重
                    }
                    else if (ht[k].weight<min2)//k号节点权重大于最小权重,小于次小权重min2
                    {
                        min2=ht[k].weight;rnode=k;//次小权重min2取k号节点权重
                    }
                }
            ht[lnode].parent=i;ht[rnode].parent=i;//权重最小的两个节点构造以i号节点为父节点的二叉树
            //新增i号节点(新增节点没有data域)
            ht[i].weight=ht[lnode].weight+ht[rnode].weight;
            ht[i].lchild=lnode;ht[i].rchild=rnode;
        }
    }
    void CreateHCode(HTNode ht[],HCode hcd[],int n)
    {
        int i,f,temp;
        HCode hc;
        for (i=0;i<n;i++)    /*根据哈夫曼树求哈夫曼编码*/
        {
            //////对叶节点i对应单词---进行编码////
            hc.start=n;//hc.cd[]中编码存放的起始位置(从start开始到n为编码存储区)(编码下标范围是0~N-1)
            temp=i;//当前节点c取叶节点i
            f=ht[temp].parent;        
            while (f!=-1)//当前节点c存在父节点
            {
                if (ht[f].lchild==temp)//当前c节点是其父节点的左孩子节点
                    hc.cd[hc.start--]='0';//编码
                else hc.cd[hc.start--]='1';//当前c节点是其父节点的右孩子节点
        
                temp=f;//取c的父节点为新的当前节点c
                f=ht[temp].parent;//取当新的当前节点c的父节点f
            }
            hc.start++;//(从下标hc.start开始存储到hc.start=n结束)---start指向哈夫曼编码最开始字符
            ////////////////////////////////////////
            hcd[i]=hc;//叶节点i对应单词的哈夫曼编码hc存入编码表hcd[i]  
        }
    }
    void DispHCode(HTNode ht[],HCode hcd[],int n)//输出哈夫曼编码
    {
        int i,k;
        int CodeSum=0,WeightAdd=0;
        printf("输出哈夫曼编码:\n"); 
        for (i=0;i<n;i++)//对于每个单词(叶节点)
        {
            int CountLen=0;
            printf("%s:\t",ht[i].data);//输出单词
            for (k=hcd[i].start;k<=n;k++)//输出单词(叶节点)编码
            {
                printf("%c",hcd[i].cd[k]);
                CountLen++;//统计i号单词编码长度
            }
            WeightAdd+=ht[i].weight;//统计叶节点权重和(即所有单词总数)
            CodeSum+=ht[i].weight*CountLen;//得到总的编码量(即所有单词的编码总量)
            printf("\n");
        }
        printf("平均每个单词的编码长度=%g\n",1.0*CodeSum/WeightAdd);//输出每个单词的编码平均长度
    }
    
    
    
    /*
    输出哈夫曼编码:
    The:    01
    of:     101
    a:      001
    to:     000
    and:    1110
    in:     1101
    that:   11110
    he:     11001
    is:     11000
    at:     10011
    on:     10010
    for:    10001
    His:    10000
    are:    111111
    be:     111110
    平均每个单词的编码长度=3.56208
    
    Press any key to continue
    */



  • 相关阅读:
    【转】数据库中查询记录时是否每次只能使用一个索引?
    【转】MySQL理解索引、添加索引的原则
    【转】.htaccess详解及.htaccess参数说明
    【转】BASE64编码简介
    【转】联想笔记本进入u盘启动项操作方法详解
    【转】UEFI是什么?与BIOS的区别在哪里?UEFI详解!
    55. Jump Game
    54. Spiral Matrix
    53. Maximum Subarray
    52. N-Queens II
  • 原文地址:https://www.cnblogs.com/IThaitian/p/2752382.html
Copyright © 2011-2022 走看看