签到

06月21日
尚未签到

共有回帖数 0

    顾我心安

    等级:
    #include stdio.h
    #include stdlib.h
    #define MaxSize 50
    typedef struct{
       char c;                       //代码;
       int w;                       //代码权值;
       char code[MaxSize];           //代码的Huffman编码;
       }HuffCode[MaxSize];
    typedef struct{
       int Weight;                   //权值;
       int LChild,RChild,Parent;
       }HTNode,HuffTree[MaxSize];
    //================================================================================
    void HuffmanTree(HuffTree HT,int length,HuffCode hc);        //生成Huffman树;
    void SelectHTNode(HuffTree HT,int n,int *min1,int *min2);    //查找最小和次小序号;
    void HuffmanCode(HuffTree HT,int len,HuffCode hc);            //生成Huffman编码;
    //================================================================================
    int main(void)
    {
       HuffTree HT;       //Huffman树;
       HuffCode HC;       //Huffman编码;
       int i,len;
       printf("  Huffman编码生成程序  ttby Haroldi.nn  请帮助评价一下思路及改善意见!t多谢了:-)...nnnn");
       printf("n输入代码数量:");    scanf("%d",&len); system("cls");printf("代码数量:%2dnn",len);
       printf("输入代码及权值(e.g.:  "a16[回车]" ):n");
       for(i=1;i = len;i++)
       {
           while(getchar() != 'n')    NULL;
           printf("No.%2d:  ",i);
           HC.c = getchar();
           scanf("%d",&HC.w);
       }
       HuffmanTree(HT,len,HC);
       HuffmanCode(HT,len,HC);

       printf("n输出Huffman编码:n");
       for(i = 1;i=len;i++)
       {
           printf("n %c :",HC.c);
           puts(HC.code);
       }
    //测试Huffman树结构;
       printf("nn输出Huffman树结构:");system("pause");
       printf("nHT:t权值t双亲t左孩子t右孩子n");
       for(i = 1;i2*len;i++)
       {
           if(i = len)    printf("(%c)",HC.c);
           printf("%2d:t %2d;t%2d,t %2d,t %2d.n",
               i,HT.Weight,HT.Parent,HT.LChild,HT.RChild);
       }
       return 0;
    }
    //================================================================================
    void HuffmanTree(HuffTree HT,int length,HuffCode hc)       //Huffman树初始化;
    {
       int i,min1,min2;
       HT[0].Weight = 65535;
       for(i = 1;i = length;i++)
       {
           HT.Weight = hc.w;
           HT.LChild = HT.RChild = HT.Parent = -1;
       }
       for(;i  2*length;i++)            //i初值 = length+1;
       {
           HT.LChild = HT.RChild = HT.Parent = -1;
       }

       for(i = length+1;i  2*length;i++)
       {
           SelectHTNode(HT,i,&min1,&min2);
           HT[min1].Parent = i;
           HT[min2].Parent = i;
           HT.LChild = min1;
           HT.RChild = min2;
           HT.Weight = HT[min1].Weight + HT[min2].Weight;
       }
    }
    //================================================================================
    void SelectHTNode(HuffTree HT,int n,int *min1,int *min2)    //查找最小和次小序号;
    {
       int i;
       *min1 = *min2 = 0;
       for(i = 1;i  n;i++)
       {
           if(HT.Parent == -1)
           {
               if(HT[*min1].Weight = HT.Weight)
               {
                   *min2 = *min1;
                   *min1 = i;
               }
               else if(HT[*min2].Weight  HT.Weight)    *min2 = i;
           }
       }
    }
    //================================================================================
    void HuffmanCode(HuffTree HT,int len,HuffCode hc)         //生成Huffman编码;
    {
       int i,j,tc,Stack[MaxSize],top = -1;
       char flag[MaxSize];
       HTNode th;
       for(i = 1;i = len;i++)
       {
           top = -1;                        //栈初始化;
           j = 0;                            //hc.code串首位置偏移;
           th = HT;                        //当前结点th;
           tc = i;                            //当前结点标记tc;
           while(th.Parent != -1)
           {            //当前结点th双亲P入栈,由P的孩子是th,确定flag;确定下次结点标记tc;
               Stack[++top] = th.Parent;
               if(HT[th.Parent].LChild == tc)    {flag[top] = 'L'; tc = th.Parent;}
               if(HT[th.Parent].RChild == tc)    {flag[top] = 'R'; tc = th.Parent;}
               th = HT[Stack[top]];        //下一结点;
           }                                
           while(top != -1)
           {
               if(flag[top] == 'L')    hc.code[j++] ='0';
               else                    hc.code[j++] ='1';
               Stack[top--];                //出栈;
           }
           hc.code[j] ='';            //当前串结束;
       }          
    }
    //================================================================================

    哈夫曼树

    在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUFFMAN)树和哈夫曼编码。哈夫曼编码是哈夫曼树的一个应用。哈夫曼编码应用广泛,如JPEG中就应用了哈夫曼编码。  

    首先介绍什么是哈夫曼树。哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明哈夫曼树的WPL是最小的。

    哈夫曼在上世纪五十年代初就提出这种编码时,根据字符出现的概率来构造平均长度最短的编码。它是一种变长的编码。在编码中,若各码字长度严格按照码字所对应符号出现概率的大小的逆序排列,则编码的平均长度是最小的。(注:码字即为符号经哈夫曼编码后得到的编码,其长度是因符号出现的概率而不同,所以说哈夫曼编码是变长的编码。)

    然而怎样构造一棵哈夫曼树呢?最具有一般规律的构造方法就是哈夫曼算法。一般的数据结构的书中都可以找到其描述:

    一、对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。(为方便在计算机上实现算法,一般还要求以Ti的权值Wi的升序排列。)

    二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。

    三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。

    四、重复二和三两步,直到集合F中只有一棵二叉树为止��

    楼主 2016-01-08 11:00 回复

共有回帖数 0
  • 回 帖
  • 表情 图片 视频
  • 发表

登录直线网账号

Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号 意见反馈 | 关于直线 | 版权声明 | 会员须知