当前您在:主页 > 头条 >

新濠天地的原理和构建 - enumhack

日期:2019-02-04   关注热度:℃  所属栏目: 头条

1. 新濠天地的安排

    假设N个权值使分裂为w1, w2, ..., Wn的填料。安排新濠天地的算法代表列举如下:

    1)将这N个节疤使分裂作为N棵树仅含一任一某一节疤的二叉树,包括丛林F.

    2)安排一任一某一新填料,并从F中拔取两棵根节疤权值最小的树作为新填料的左、右子树,并且将新填料的权值置为左、右子树上根节疤的权                    

    值积和。

    3)从F中截方才选出的两棵树,同时将新承受的树进入F中。

    4)反复级别2和3,直至F中只剩一棵树为止。

2. 哈夫曼编码

       哈夫曼编码是一种被到处运用并且非常奇特的无效的资料紧缩编码,它是可变的上浆编码。可变的长编码即可以用手柄状物处置字母串中两样印运用不同长的多少表现,可变的长编码比使停止流通上浆编码好很多,可以对频率高的印赠送短编码,而对频率较低的印则赠送较长一点点的编码,原来如此可以使刻薄的编码上浆减短,起到紧缩资料的成了解的事。

       哈夫曼编码是前缀编码。即使心不在焉一任一某一编码是另一任一某一编码的前缀,则称这么样的编码为前缀编码。对前缀编码的解码也对立复杂的,由于心不在焉一任一某一码是另一任一某一编码的前缀,因而可以辨出出第一任一某一编码,将它翻译家为原码,再对剩下的的编码证件反复异样柄状物。

        哈夫曼编码率先要安排一棵新濠天地,率先,将每个呈现的印当做一任一某一孤独的节疤,其权值作为它呈现的频度(或次数),而且安排新濠天地。显然领地印填料均呈如今生叶节疤中。咱们可以将印的编码解说为从根至该印按某路线发送上邮票的序列,时髦的邮票为0表现"转向左孩子",邮票为1表现为"转向右孩子"。 列举如下图,矩形方块表现印及呈现的次数

         相应地,这棵新濠天地的WPL为:

                   WPL = 1*45 + 3 * (13+12+16) + 4 * (5+9) = 224

#ifndef _HAFFMANTREE_H
#define _HAFFMANTREE_H

/*
了解对霍夫曼编码首要级别:
 1 增大一任一某一填料阻碍用来保证金树的填料传达
 2 设定初值
 3 从中找出权值最小和权值次小填料而且增大这两个填料的双亲填料权值最小填料是该双亲填料的左孩子次小为右孩子而且将该双亲填料进入到填料阻碍中并邮票为已进入
 4 反复三级别觉悟霍夫曼树安排成
*/
#include
#include<malloc.h>
#define LEN_CODE sizeof(HaffmanCode)
#define LEN_NODE sizeof(haffmannode)
#define MAXWEIGHT 1000 //用来回忆最大的权值数#define MaxBits 30 //用来回忆转变后的编码

typedef struct HaffManTree
{
    int weight;  //保证金填料的权值int LeftChild,RightChild,Parent;  //采取仿效支持办法保证金填料的摆布孩子和双亲下标int flag;  //用来断定该填料条件曾经进入了霍夫曼树中( 0表现未进入,1表现曾经进入 )}haffmannode;

typedef struct HaffMancode
{
    int bits[MaxBits]; //用来保证金编码int weight;  //用来保证金对应的权值int start; //保证金编码的起点臀部}HaffmanCode;

void MakeTree(int weight[],int n,haffmannode haffmantree[]);
void MakeCode(haffmannode haffmantree[],int n,HaffmanCode haffmancode[]);
void DispCode(char temp[],haffmannode tree[],HaffmanCode Code[],int n);

#endif
/*
功用作用的了解
*/
#include""void MakeTree(int weight[],int n,haffmannode haffmantree[])
{
    int i,j,m1,m2,x1,x2;
    //设定初值(n个叶填料通共 2*n-1 个填料)for(i=0;i < 2*n-1; i++)
    {
        if(i < n)  //处置 n 个生叶填料        {
            haffmantree[i].weight=weight[i];
        }
        else haffmantree[i].weight=0;
        haffmantree[i].LeftChild=-1;  //开端时分让摆布孩子和双亲的下标为 -1 
        haffmantree[i].RightChild=-1;
        haffmantree[i].Parent=-1;
        haffmantree[i].flag=0;  
    }
    
    //每回从中选出权值最小的和次小的包括树的摆布子树
    //处置 n-1 个非生叶填料for(i=0; i < n-1;i++)
    {
        m1=m2=MAXWEIGHT;
        x1=x2=0;
        //从有权值的填料中查找 m1 用来保证金权值最小的 m2 用来保证金权值次小的 x1 用来保证金权值最小的下标 x2 用来保证金权值次小的下标for(j=0;j < n+i; j++)
        {
            if(haffmantree[j].weight < m1 && haffmantree[j].flag==0)
            {
                m2=m1; 
                x2=x1;
                m1=haffmantree[j].weight;
                x1=j;
            }
            elseif(haffmantree[j].weight < m2 && haffmantree[j].flag==0)
            {
                m2=haffmantree[j].weight;
                x2=j;
            }
        }
        haffmantree[x1].Parent=n+i; // 譬如第一任一某一双亲填料的下标执意 n 居第二位的个双亲填料的下标执意 n+1 --------
        haffmantree[x2].Parent=n+i;
        haffmantree[x1].flag=1;
        haffmantree[x2].flag=1;
        haffmantree[n+i].weight=haffmantree[x1].weight + haffmantree[x2].weight;  //权值概括
        //printf("%d
",haffmantree[n+i].weight);
        haffmantree[n+i].LeftChild=x1;
        haffmantree[n+i].RightChild=x2;    
    }
}

//本作用用来了解对霍夫曼编码的处理void MakeCode(haffmannode haffmantree[],int n,HaffmanCode haffmancode[])
{
    int i,j;
    int Child,Parent;
    HaffmanCode *code;
    code=(HaffmanCode *)malloc(LEN_CODE);  //用来保证金暂时资料for(i=0;i < n ;i++)
    {
        code->weight=haffmantree[i].weight;
        code->start=0; 
        Child=i;    
        Parent=haffmantree[Child].Parent;
        while(Parent != -1) //当双亲填料不为根填料时分        {
            if(haffmantree[Parent].LeftChild==Child)  //即使现在的填料是双亲填料的左孩子就将0进入到该编码中即使是右孩子就将1进入到编码中
                code->bits[code->start]=0;
            else
                code->bits[code->start]=1;
            code->start++;  
            Child=Parent;  //自底向上自负的断定
            Parent=haffmantree[Child].Parent;
        }
        for(j=0;j < code->start;j++) //把该编码进入到对应的编码阻碍中        {
            haffmancode[i].bits[j]=code->bits[j];
        }
        haffmancode[i].weight=code->weight; //把对应的权值进入到对应编码阻碍的权值中去
        haffmancode[i].start=code->start; //将完毕臀部复制的出来    }
}


void DispCode(char temp[],haffmannode tree[],HaffmanCode Code[],int n) //本作用首要用来了解哈夫曼编码的出口{
    int i,j;
    printf("
出口霍夫曼编码:

");
    for(i=0;i)
    {
        printf("印= %c 	Weight= %d 	
印= %c 	Code=",temp[i],tree[i].weight, temp[i]);
        for(j=(Code[i].start-1);j>=0;j--)//出口编码        {
            printf("%d",Code[i].bits[j]);
        }
        printf("

");
    }
}