鱼C论坛

 找回密码
 立即注册
查看: 5990|回复: 7

哈夫曼编码的代码 求大神解答 怎么才能正确运行

[复制链接]
发表于 2020-11-1 18:32:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#include<iostream>
using namespace std;

typedef struct{
        int weight;
        int parent,lchild,rchild;
}HTNode,*HuffmanTree;

int min(HUffmanTree HT,int m)
{
        int i=0;
        int min;
        int min_weight;
        while(HT[i].parent!=0)
                i++;
        min_weight=HT[i].weight;
        min=i;
        for(i=1;i<m;i++)
        {
                if(HT[i].weight<min_weight && HT[i].parent==0)
                {
                        min_weight=HT[i].weight;
                        min=i;
                }
        }
        HT[min].parent=1;
        return min;
}
void Select(HuffmanTree HT,int m,int &s1,int &s2)
{
        int min1,min2;
        min1=min(HT,m);
        min2=min(HT,m);
}

void CreatHuffmanTree(HuffmanTree &HT,int n)
{
        if(n<=1) return;
        int m = 2*n-1;
        HT = new HTNode[m+1];
        int s1,s2;
        for(int i=1;i<=m;i++)
        {
                HT[i].parent=0;
                HT[i].lchild=0;
                HT[i].rchild=0;
        }
        for(int j=1;j<=n;++j)
                cin>>HT[j].weight;
        for(int k=n+1;k<=m;k++)
        {
                Select(HT,k-1,s1,s2);
                HT[s1].parent=k;
                HT[s2].parent=k;
                HT[k].lchild=s1;
                HT[k].rchild=s2;
                HT[k].weight=HT[s1].weight+HT[s2].weight;
        }
}
typedef char **HuffmanCode;
void CreatHuffmanCode(Huffman HT,HuffmanCode &HC,int n)
{
        HC=new char*[n+1];
        cd=new char[n];
        cd[n-1]='\0';
        for(i=1;i<=n;i++)
        {
                start=n-1;
                c=i;f=HT[i].parent;
                while(f!=0)
                {
                        --start;
                        if(HT[f].lchild==c)
                                cd[start]='0';
                        else
                                cd[start]='1';
                        c=f;
                        f=HT[f].parent;
                }
                HC[i]=new char[n-start];
                strcpy(HC[i],&cd[start]);
        }
        delete cd;
}
int main()
{
        int n;


        cout<<"请输入结点个数:"<<endl;
        cin>>n;
        HTNode *HuffmanTree=new HTNode[2*n-1];
        int *weight=new int[n];
        char **HC=new char*[n];

        cout<<"请输入"<<n<<"个权值:";
        CreatHuffmanTree(HuffmanTree,n);
        CreatHuffmanCode(Huffman HT,Hsuffmancode HC,n);
        cout<<"输出哈夫曼编码:"<<endl;
        return 0;
}
       
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-11-1 19:05:40 | 显示全部楼层
没有看你的错误,提供个完整的仅供参考
#include<iostream>
#include<string>
#include<limits.h>
using namespace std;

struct HNode                  //树结点(静态三叉链表)
{
        char name;   //结点内容
        int weight;  //结点权重
        int parent;  //双亲数组下标
        int LChild;  //左孩子数组下标
        int RChild;  //右孩子数组下标
};

struct HCode             //编码表中的每个元素
{
        char data;   //字符内容
        string code;  //对应编码 
};

static int a[128] = { 0 };  //权值数组
static char name[128] = ""; //字符内容
static int n = 0;           //字符种类数

class Huffman
{
private:
        HNode* HTree = NULL;                   //哈夫曼树
        HCode* HCodeTable = NULL;            //存储编码表
        int N=0;                             //叶子数量
        void code(int i, string newcode);    //递归函数,对第i个结点编码
public:
        
        void CreateHTree(int a[], int n, char *name);  //创建哈夫曼树
        void CreateCodeTable();                        //创建编码表
        void Encode(char* d,string &s);               //编码 
        void Decode(char* s,char *d);                 //解码 
        void PrintHCodeTable();                       //打印编码表
        void PrintHTree();                            //打印哈夫曼树 
        void printHfmTree(int root, int height, ostream& out);//直观打印
        void Analyze(string s,char *d);               //分析压缩效果 
        ~Huffman();                                   //析构 
};

  //a[]为每种字符的权值,n为字符种类,name[]为各个字符的内容
 void Huffman::CreateHTree(int a[], int n, char *name)
{
        N = n;                        //叶子数
        HCodeTable = new HCode[N];
        HTree = new HNode[2 * N - 1];   //初始化树的每个结点
        for (int i = 0; i < N; i++)
        { 
                HTree[i].name = name[i];
                HTree[i].weight = a[i];
                HTree[i].LChild = HTree[i].RChild = HTree[i].parent = -1;
                HCodeTable[i].data = name[i];
        }

        int x=0, y=0;                    //开始建哈夫曼树
        for (int i = n; i < 2 * N - 1; i++)          //N个叶子,2*N-1个结点
        {
                int min1 = INT_MAX;//最小值,INT_MAX在<limits.h>中定义的
                int min2 = INT_MAX;//次小值
                for(int j = 0; j < i;j++)
                {
                        if (HTree[j].parent == -1)
                        {
                                if (HTree[j].weight < min1)
                                {
                                        min2 = min1;
                                        min1 = HTree[j].weight;
                                        y = x;
                                        x = j;
                                }
                                else if ((HTree[j].weight >= min1) && (HTree[j].weight < min2))
                                {
                                        min2 = HTree[j].weight;
                                        y = j;
                                }
                                else { ; }
                        }
                }
                HTree[x].parent = HTree[y].parent = i;   //父结点下标(实际意义:三结点相连)
                HTree[i].weight = HTree[x].weight + HTree[y].weight;
                HTree[i].LChild = x;
                HTree[i].RChild = y;
                HTree[i].parent = -1;    //待定,默认-1
        }
}

  //递归函数,对第i个结点编码
void Huffman::code(int i, string newcode)   
{
        if (HTree[i].LChild == -1)  //左子树空
        {
                HCodeTable[i].code = newcode;
                return;
        }
        code(HTree[i].LChild, newcode + "0");
        code(HTree[i].RChild, newcode + "1");
}

  //生成编码表
void Huffman::CreateCodeTable()
{
        code(2 * N - 2, "");
}

  //打印编码表
void Huffman::PrintHCodeTable()
{
        cout << "\t\t\t\t所建字符编码表如下:" << endl;
        cout << "\t\t\t\t--------------------------" << endl;
        cout << "\t\t\t\t字符内容\t" << "对应编码\t" << endl;
        for (int i = 0; i < N; i++)
        {
                cout <<"\t\t\t\t"<< HCodeTable[i].data << "\t\t" << HCodeTable[i].code << endl;
        }
        cout << "\t\t\t\t--------------------------" << endl;
}

  //析构
Huffman::~Huffman()
{
        delete[]HTree;
        delete[]HCodeTable;
}

static string coded_string = "";   //用于存储对象字符串的编码串
static char text_out[] = "";       //存储解码结果

  //编码 d为字符串,s为编码后的编码串
void Huffman::Encode(char* d,string &s)      
{
        int k = 0;
        while (d[k] != '\0')
        {
                for (int i = 0; i < N; i++)
                {
                        if (HCodeTable[i].data == d[k])
                        {
                                s = s + HCodeTable[i].code;
                                break;
                        }
                }
                k++;
        }
        cout << "\t\t\t\t编码结果如下: "<< endl;
        cout <<"\t\t\t\t"<< s << endl;
}

  // 解码 s为编码串,d为解码后的字符串
void Huffman::Decode(char* s,char* d)
{
        while (*s != '\0')
        {
                int parent = 2 * N - 2;      //根节点在HTree中的下标(共2*N-1个结点)
                while (HTree[parent].LChild != -1)  //有左孩子,不是叶子结点
                {
                        if (*s == '0')
                                parent = HTree[parent].LChild;//左拐
                        else
                                parent = HTree[parent].RChild;//右拐
                        s++;//后移一位
                }//目的:找下标parent
                *d = HCodeTable[parent].data;
                d++;
        }
}

  //打印Huffman树
void Huffman::PrintHTree()
{
        cout << "\t\t\t\t所建哈夫曼静态链表示如下:" << endl;
        cout << "\t\t\t\t==============================================" << endl;
        cout << "\t\t\t\t位置\t"<<"内容\t"<<"权值\t"  << "双亲\t" << "左孩子\t" << "右孩子\t" << endl;
        for (int i = 0; i < N * 2 - 1; i++)
        {
                cout <<"\t\t\t\t"<<i<<"\t"<<HTree[i].name<<"\t"<< HTree[i].weight << "\t" << HTree[i].parent << "\t"  << HTree[i].LChild << "\t" << HTree[i].RChild<< endl;
        }
        cout << "\t\t\t\t==============================================" << endl;
        //可视化直观打印
        cout << "\t\t\t\t该哈夫曼树打印如下(横向打印):" << endl << endl;
        printHfmTree(2 * N - 2, 0, cout);

}

//递归实现直观打印
void Huffman::printHfmTree(int root, int height, ostream& out)
{
        char branches[] = { " /\\<" };    //树枝图形
        if (root != -1)   
        {
                //先打印当前结点的右子树,并且深度+1
                printHfmTree(HTree[root].RChild, height + 1, out);  //递归

                for (int i = 0; i < height; i++) out << "\t";//根据深度,右移

                out << HTree[root].weight;//输出权值

                //叶结点,则再打印出相应的字符
                if (HTree[root].LChild == -1 && HTree[root].RChild == -1) 
                        out << "(" << HTree[root].name << ")";

                //打印树枝
                out << branches[((HTree[root].LChild != -1) << 1) | (HTree[root].RChild != -1)];

                //换行,打印当前结点的左子树
                out << endl;
                printHfmTree(HTree[root].LChild, height + 1, out);  //递归
        }
}

//s为编码串,d为原字符串
void Huffman::Analyze(string s, char* d)           
{
        char* s1 = (char*)s.data();
        double m = 0, n = 0;
        while (*s1 != '\0') { m++; s1++; }
        while (*d != '\0') { n++; d++; }
        cout << "\t\t\t\t压缩比为:" << 100 * (m / 8.0) / n << "%" <<"\n"<< endl;
}

  //测试函数
int main()            
{
        Huffman huffman1;  //建树(默认构造)
        cout << "请输入需要操作的字符串:" << endl;
        char text[128];
        cin.getline(text, 128, '\n');
        text[strlen(text) + 1] = '\0';

        int str_length = sizeof(text) / sizeof(text[0]);
        char Character_range[] = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 !"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~";
        //给定范围,支持所有可显示字符
        for (int i = 0; i < str_length; i++)   //遍历text
        {
                bool p = 0;   //标记
                for (int j = 0; j < n; j++)
                {
                        if (text[i] == name[j]) 
                        {
                                a[j]++; p = 1;
                                break;
                        }
                }
                for (int j = 0; j < strlen(Character_range)+1 && p == 0; j++)
                {
                        if (text[i] == Character_range[j])
                        {
                                name[n] = text[i];
                                a[n]++; n++;
                                break;
                        }
                }
        }
        int length = 0;   //记录长度
        for (int i = 0; i < 128; i++)
        {
                length += a[i];
        }

        char* coded_str = (char*)coded_string.data();  //类型转换,为参数准备
        cout << "\t\t\t\t\t 给定字符串统计结束,系统就绪!\n" << endl;

                cout << "\t\t\t\t       Welcome to the Huffman coding  system!       \n";
                cout << "\t\t\t\t***************************************************\n";
                cout << "\t\t\t\t *    │1.打印Huffman树       2.打印编码表     │    *\n";
                cout << "\t\t\t\t *    │                                       │    *\n";
                cout << "\t\t\t\t *    │3.编码并打印          4.解码并打印     │    *\n";
                cout << "\t\t\t\t *    │                                       │    *\n";
                cout << "\t\t\t\t *    │5.计算压缩率          6.退出程序       │    *\n";
                cout << "\t\t\t\t***************************************************\n";
                cout << endl;

                huffman1.CreateHTree(a, n, name);//建树
                huffman1.CreateCodeTable();      //建表
        
                int select;
                do                                   
                {
                        cout << "\t\t\t\t请选择操作方式 (1~6):" << endl;
                        cin >> select;
                        if (select > 6)
                                cout << "错误操作,请重新输入!" << endl;
                        else
                        switch (select) {

                        case 1:
                                huffman1.PrintHTree();
                                break;

                        case 2:  
                                huffman1.PrintHCodeTable();
                                break;

                        case 3:  
                                huffman1.Encode(text,coded_string);
                                break;

                        case 4:                        
                                coded_str = (char*)coded_string.data();  //类型转换
                                huffman1.Decode(coded_str, text_out);
                                text_out[length - 2] = '\0';
                                cout << "\t\t\t\t解码后的字符串为:" << "\n"<<text_out << "\n"<<endl;
                                break;

                        case 5:                                                
                                huffman1.Analyze(coded_string, text);
                                break;

                        case 6:
                                cout << "\t\t\t\t\tThank you for using!" << endl;
                        }
                } while (select != 6);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-2 18:50:07 | 显示全部楼层
昨非 发表于 2020-11-1 19:05
没有看你的错误,提供个完整的仅供参考

我运行了这个也有错误
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-11-2 19:05:59 | 显示全部楼层
KAaha 发表于 2020-11-2 18:50
我运行了这个也有错误

发报错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-2 20:31:03 | 显示全部楼层

D:\vc6.0\vc6.0 (2)\ka.cpp(28) : error C2252: 'HTree' : pure specifier can only be specified for functions
D:\vc6.0\vc6.0 (2)\ka.cpp(29) : error C2252: 'HCodeTable' : pure specifier can only be specified for functions
D:\vc6.0\vc6.0 (2)\ka.cpp(30) : error C2252: 'N' : pure specifier can only be specified for functions
D:\vc6.0\vc6.0 (2)\ka.cpp(48) : error C2065: 'N' : undeclared identifier
D:\vc6.0\vc6.0 (2)\ka.cpp(49) : error C2065: 'HCodeTable' : undeclared identifier
D:\vc6.0\vc6.0 (2)\ka.cpp(49) : error C2440: '=' : cannot convert from 'struct HCode *' to 'int'
        This conversion requires a reinterpret_cast, a C-style cast or function-style cast
D:\vc6.0\vc6.0 (2)\ka.cpp(50) : error C2065: 'HTree' : undeclared identifier
D:\vc6.0\vc6.0 (2)\ka.cpp(50) : error C2440: '=' : cannot convert from 'struct HNode *' to 'int'
        This conversion requires a reinterpret_cast, a C-style cast or function-style cast
D:\vc6.0\vc6.0 (2)\ka.cpp(53) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(53) : error C2228: left of '.name' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(54) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(54) : error C2228: left of '.weight' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(55) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(55) : error C2228: left of '.LChild' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(55) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(55) : error C2228: left of '.RChild' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(55) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(55) : error C2228: left of '.parent' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(56) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(56) : error C2228: left of '.data' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(60) : error C2374: 'i' : redefinition; multiple initialization
        D:\vc6.0\vc6.0 (2)\ka.cpp(51) : see declaration of 'i'
D:\vc6.0\vc6.0 (2)\ka.cpp(66) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(66) : error C2228: left of '.parent' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(68) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(68) : error C2228: left of '.weight' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(71) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(71) : error C2228: left of '.weight' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(75) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(75) : error C2228: left of '.weight' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(75) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(75) : error C2228: left of '.weight' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(77) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(77) : error C2228: left of '.weight' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(83) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(83) : error C2228: left of '.parent' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(83) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(83) : error C2228: left of '.parent' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(84) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(84) : error C2228: left of '.weight' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(84) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(84) : error C2228: left of '.weight' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(84) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(84) : error C2228: left of '.weight' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(85) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(85) : error C2228: left of '.LChild' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(86) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(86) : error C2228: left of '.RChild' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(87) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(87) : error C2228: left of '.parent' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(94) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(94) : error C2228: left of '.LChild' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(96) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(96) : error C2228: left of '.code' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(99) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(99) : error C2228: left of '.LChild' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(100) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(100) : error C2228: left of '.RChild' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(117) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(117) : error C2228: left of '.data' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(117) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(117) : error C2228: left of '.code' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(125) : error C2541: delete : cannot delete objects that are not pointers
D:\vc6.0\vc6.0 (2)\ka.cpp(126) : error C2541: delete : cannot delete objects that are not pointers
D:\vc6.0\vc6.0 (2)\ka.cpp(140) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(140) : error C2228: left of '.data' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(142) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(142) : error C2228: left of '.code' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(158) : error C2109: subscript requires array or pointer type
D:\vc6.0\vc6.0 (2)\ka.cpp(158) : error C2228: left of '.LChild' must have class/struct/union type
D:\vc6.0\vc6.0 (2)\ka.cpp(158) : fatal error C1903: unable to recover from previous error(s); stopping compilation
执行 cl.exe 时出错.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-11-2 20:39:46 | 显示全部楼层
啊这,我这里运行没问题啊,你用的啥编译器??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-2 20:54:00 | 显示全部楼层
昨非 发表于 2020-11-2 20:39
啊这,我这里运行没问题啊,你用的啥编译器??

visual c++
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-28 19:47:51 | 显示全部楼层
昨非 发表于 2020-11-1 19:05
没有看你的错误,提供个完整的仅供参考

需要加头文件<string.h>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-25 03:12

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表