用贪心算法求解哈夫曼编码

【问题描述】

使用贪心算法编程,求解霍夫曼编码问题node

【输入形式】

输入一个字符串ios

【输出形式】

输出该字符串建成哈夫曼树的最小权重c++

【样例输入】

ABCBDAB

【样例输出】

13

【样例说明】

该字符串中B的频数为3,A的频数为2,C、D的频数为1,建成哈夫曼树后最小权重为3×1+2×2+1×3+1×3=13web

c++代码

#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 *inputStr;
//存放字符节点的数组
Node nodes[200 + 199];
//总的节点数
int total;
//记录当前所处的深度
int depth;
//统计数量
int getNum(char *in, char c)
{
    int num = 0;
    for (int i = 0; i <= strlen(in); i++)
    {
        if (*(in + i) == c) num++;
    }
    return num;
}
//统计输入的字符种类(当时写的这方法很差,我的推荐使用hash存储的方式统计)
int getTypeChar(char *in)
{
    inputStr = (char *)malloc(sizeof(char)*200);
    memset(inputStr, '\0', sizeof(inputStr));
    int p = 0;
    bool isAdded;
    //cout<<strlen(in)<<endl;
    for (int i = 0; i<strlen(in); 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;
}