• 如何建立一棵哈夫曼树并且输出压缩码


    算法:1、给定一个具有n个权值{ w1,w2,………wn }的结点的集合 F = { T1,T2,………Tn } 2、 初始时,设集合 A = F。 3、 执行 i = 1 至 n -1 的循环,在每次循环时执行以下操作 从当前集合中选取权值最小、次最小的两个结点,以这两个结点作为内部结点 bi 的左右儿子,bi 的权值为其左右儿子权值之和。 在集合中去除这两个权值最小、次最小的结点,并将内部结点bI 加入其中。这样,在集合A中,结点个数便减少了一个。 这样,在经过了n-1 次循环之后,集合A中只剩下了一个结点,这个结点就是根结点。

    哈夫曼树的存储:在哈夫曼树中,每个要编码的元素是一个叶结点(度数为零),其它结点都是度数(度数就是有多少个子节点)为2的节点 一旦给定了要编码的元素个数,由n0=n2+1可知哈夫曼树的大小为2n-1 哈夫曼树可以用一个大小为2n的数组来存储。0节点不用,根存放在节点1。叶结点依次放在n+1到2n的位置 每个数组元素保存的信息:结点的数据、权值和父结点和左右孩子的位置。

    代码实现:

    //哈夫曼树及其编码,两个结构体,第一个是用来构造哈夫曼树的,第二个是用来保存压缩码的
    #include<iostream>
    using namespace std;
    struct hfnode{
        char data;//字符
        int weight;//字符的个数,也就是权值
        int parent,left,right;//父节点、左子树、右子树的数组下标
    };
    struct node{
        char data;//字符
        char a[1000];//用于保存压缩码
        int num;//压缩码的长度
    };
    struct node *hftree(char str[],int d[],int size)
    {
        int lenth=size*2,min1,min2,x,y,i,j;
        struct hfnode *hf;
        struct node *p;
        hf=(struct hfnode *)malloc(lenth*sizeof(struct hfnode));
        p=(struct node *)malloc(size*sizeof(struct node));
        for(i=size;i<lenth;i++)//size到(lenth-1)用来存放叶子节点
        {
            hf[i].data=str[i-size];
            hf[i].weight=d[i-size];
            hf[i].parent=hf[i].left=hf[i].right=0;
        }
        for(i=size-1;i>0;i--)//哈夫曼树的构造
        {
            min1=min2=100000000;x=y=0;//min1用来保存最小的,min2用来保存次小的
            for(j=i+1;j<lenth;j++)
            {
                if(min1>hf[j].weight&&hf[j].parent==0)
                {
                    min2=min1;y=x;
                    min1=hf[j].weight;
                    x=j;
                }
                else if(min2>hf[j].weight&&hf[j].parent==0)
                {
                    min2=hf[j].weight;
                    y=j;
                }
            }
            if(x>y)
                swap(x,y);
            hf[i].weight=min1+min2;//新的节点的形成
            hf[i].parent=0;
            hf[i].left=x;
            hf[i].right=y;
            hf[x].parent=i;
            hf[y].parent=i;
        }
        for(i=size;i<lenth;i++)//求出各个字符的压缩码
        {
            int t1,t2;
            p[i-size].data=hf[i].data;
            p[i-size].num=0;
            t1=hf[i].parent;//父节点的数组下标
            t2=i;//自身的数组下标
            while(t1>0)
            {
                if(hf[t1].left==t2)
                    p[i-size].a[p[i-size].num++]='0';
                else
                    p[i-size].a[p[i-size].num++]='1';
                t2=t1;
                t1=hf[t1].parent;
            }
        }
        return p;
    }
    int main()
    {
        char str[1000];
        int b[26],c[26],i,j,n,size;
        struct node *temp;
        while(scanf("%d",&n)!=EOF)//测试案例的个数
        {
           getchar();
           while(n--)
           {
               size=0;
               memset(b,0,sizeof(b));
               scanf("%s",str);
               for(i=0;str[i]!='\0';i++)
                   b[str[i]-'a']++;
               for(i=0;i<26;i++)
                   if(b[i]!=0)
                   {
                       c[size]=b[i];
                       str[size]=i+'a';
                       size++;
                   }//c数组中保存的是各个字符的权值(也就是个数)
               temp=hftree(str,c,size);
               for(i=0;i<size;i++)
               {
                   printf("%c:",temp[i].data);
                   for(j=temp[i].num-1;j>=0;j--)
                       printf("%c",temp[i].a[j]);
                   printf("\n");
               }
           }
        }
        return 0;
    }
  • 相关阅读:
    常见设备标记长度查询
    word怎么在方框中打对号
    shell dict 操作
    词表数据转换
    GoLand tool tips
    mac使用技巧
    人生三大陷阱
    【js重学系列】执行上下文
    uniapp-ui库
    【js重学系列】instanceof
  • 原文地址:https://www.cnblogs.com/jiangjing/p/2862828.html
Copyright © 2020-2023  润新知