哈夫曼编码

原文链接:https://blog.csdn.net/u011507175/article/details/64920643

 哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+…+ Wn*Ln),N个权值Wi(i=1,2,…n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,…n)。可以证明哈夫曼树的WPL是最小的。 
构造哈夫曼树的算法如下: 
1)对给定的n个权值{W1,W2,W3,…,Wi,…,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,…,Ti,…, Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。 
2)在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。 
3)从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。 
4)重复2)和3),直到集合F中只有一棵二叉树为止。

输入

MT-TECH-TEAM

输出

33

至此,哈夫曼树完成构造,接下来只需要遍历统计即可。

#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;

/* 构造树*/

typedef struct Node
{ 
    char typeChar;
    int rate;

    Node *leftChild;

    Node *rightChild; 
  
}CharNode;

/* 输入字符串*/

char *inputchar;

/*存放字符节点的数组*/

Node node[200 +109];

/*总的节点数*/
int total;

int depth;//当前的深度

/*统计数量*/

int getNum(char *in ,char * c)

{  int times = 0;
  for(int i = 0; i <=strlen(in);i++)
   {
        if (*(in +i) ==c) times++;

}

return times;

}

/*统计字符种类*/

int getTypeChar(char *in)
{    
    inputstr = (char *)malloc(sizeof(char) * 200)
    //把inputstr中所有字节换做字符“0”,常用来对指针或字符串的初始化。
    memset(inputstr,'\0',sizeof(inputstr))
    int p = 0;
    bool isadded;
    for(int i =0; i< strlen(in)l; i++){
        isadded = false;
        if (p ==0)
        {
            *inputStr = *in; //指向输入的头指针
            nodes[p].typeChar = *inputStr; // 
            nodes[p].rate = getNum(in, *in);
            nodes[p].leftChild = NULL;  //叶节点
            nodes[p].rightChild = NULL;  //叶节点
            p++;
            continue;
        }
       for (int j = 0; j<p; j++)
        {
            if (*(inputStr + j) == *(in + i))
            {
                isAdded = true;
                break;
            }
        }
        if (!isAdded)
        {
            inputStr[p] = *(in + i);
            nodes[p].typeChar = *(inputStr + p);
            nodes[p].rate = getNum(in, *(in + i));
            nodes[p].leftChild = NULL;  //叶节点
            nodes[p].rightChild = NULL;  //叶节点
            p++;
        }

    }

    return p;
}
/*构造哈夫曼*/
//给排序函数使用的比较函数
bool compNode(const Node & node1, const Node & node2)
{
    if (node1.rate <= node2.rate)
    {
        return true;
    }
    else
    {
        return false;
    }
}

//哈夫曼编码
void huf(int startIndex, int endIndex, int length)
{
    sort(nodes + startIndex, nodes + startIndex + length, compNode);
    nodes[endIndex + 1].rate =
        nodes[startIndex].rate + nodes[startIndex+1].rate;
    nodes[endIndex + 1].leftChild = &nodes[startIndex];
    nodes[endIndex + 1].rightChild = &nodes[startIndex+1];
    if (endIndex + 1 != total)
    {
        huf(startIndex + 2, endIndex + 1, length - 1);
    }
}

int depthFirst(charNode *);

//遍历哈夫曼树,计算出编编码长度
int getCodeLength(int lastIndex)
{
    charNode *root = &nodes[lastIndex];
    depth = -1;
    return depthFirst(root);
}

//递归遍历
int depthFirst(charNode *node)
{
    depth++;
    if (node->leftChild == NULL && node->rightChild == NULL)
    {
        return node->rate * depth;
    }
    else
    {
        int leftSize = depthFirst(node->leftChild);
        depth--;
        int rightSize = depthFirst(node->rightChild);
        depth--;
        return  leftSize + rightSize;
    }

}

int main()
{
    char *in;
    int num;  //不同字符的数量
    in = (char *)malloc(sizeof(char) * 1000);
    while(scanf("%s", in) != EOF)
    {
        num = getTypeChar(in);
        if(num == 1)
        {
            cout<<strlen(in)<<endl;
            continue;
        }
        total = num * 2 - 1;
        huf(0, num - 1, num);

        cout<<getCodeLength(total-1)<<endl;
    }
    return 0;
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值