哈夫曼编码c++

简介: 哈夫曼编码c++

洛谷 T133213 哈夫曼编码

题目背景

(限制:)这道题不能用map等STL类,允许使用string类

题目描述

给定一个字符串,其中只包含10个阿拉伯数字和52个英文字母。要求将其进行哈夫曼编码,并输出编码及编码之后的密文,且将该密文用编码进行译码并输出。

输入格式

一个字符串,只包含10个阿拉伯数字和52个英文字母。

输出格式

前面若干行输出编码,格式如

A:001
B:100

接下来输出原串的哈夫曼编码后的密文,次行输出用哈夫曼编码的译码结果。

需要注意的是:

1、对于编码的输出,要求按照原字符ASCII码升序输出;2、对于编码和编码出来的密文,答案可能不唯一,你只需输出正确的一个即可,但必须是哈夫曼编码;

3、译码出来的原串一定是唯一的


输入输出样例

输入 #1

ABCACCDAEAE

输出 #1

A:11
B:010
C:10
D:011
E:00
110101011101001111001100
ABCACCDAEAE

说明/提示

1≤字符串长度≤3,000


参考解答:

#include<iostream>  
#include<string>  
#include<algorithm>
using namespace std;

struct Node {
    int lchild, rchild, parent;
    int weight;//权值
    string ch;//存储结点表示的字符(对于叶子结点)
    string code;//存储结点的编码(对于叶子结点)
};

class HuffmanTree {
public:
    void Select(Node huffTree[], int& min1, int& min2, int k);//找权值最小的两个字符合成“子树”
    void Huff_Tree(Node huffTree[], string str2, int n);//建树
    void Huff_Code(Node huffTree[], int n);//编码
    string Huff_Decode(Node huffTree[], int n, string s);//对字符串s解码
    string unique(string str);//对输入的str去重
};

void HuffmanTree::Select(Node huffTree[], int& min1, int& min2, int k) {//找权值最小的两个字符,min1和min2 
    int weight = 0; 
    for (int i = 0; i < k; i++) {//找最小的数min1
        if (huffTree[i].parent != -1)//判断节点是否已经选过
            continue;
        else {
            if (weight == 0) {
                weight = huffTree[i].weight;//先让weight有一个初始值
                min1 = i;
            }
            else {
                if (huffTree[i].weight < weight) {
                    weight = huffTree[i].weight;//比较求较小
                    min1 = i;
                }
            }
        }
    }
    weight = 0;
    for (int i = 0; i < k; i++) { //找“第二小”的数min2
        if (huffTree[i].parent != -1 || (i == min1))//排除已选过的数
            continue;
        else {
            if (weight == 0) {
                weight = huffTree[i].weight;
                min2 = i;
            }
            else {
                if (huffTree[i].weight < weight) {
                    weight = huffTree[i].weight;
                    min2 = i;
                }
            }
        }
    }
}

void HuffmanTree::Huff_Tree(Node huffTree[], string str2, int n) {//建树
    for (int i = 0; i < 2 * n - 1; i++) { //初始化(对于二叉哈夫曼树,若有n个叶子结点,则总共有2n-1个结点)
        huffTree[i].parent = -1;
        huffTree[i].lchild = -1;
        huffTree[i].rchild = -1;
        huffTree[i].code = "";
    }
    for (int i = 0; i < n; i++) {
        huffTree[i].ch = str2[i];
    }
    for (int k = n; k < 2 * n - 1; k++) {
        int i1 = 0, i2 = 0;
        Select(huffTree, i1, i2, k); //将i1,i2节点合成节点k
        huffTree[i1].parent = k;
        huffTree[i2].parent = k;
        huffTree[k].weight = huffTree[i1].weight + huffTree[i2].weight;
        huffTree[k].lchild = i1;
        huffTree[k].rchild = i2;
    }
}

void HuffmanTree::Huff_Code(Node huffTree[], int n) {//编码
    int i, j, k;
    string s = "";//初始化
    for (i = 0; i < n; i++) {
        s = "";
        j = i;
        while (huffTree[j].parent != -1) {//从叶子往上找到根节点  
            k = huffTree[j].parent;
            if (j == huffTree[k].lchild) {
                s = s + "0";//如果是根的左孩子,则记为0
            }
            else {
                s = s + "1";//如果是根的右孩子,则记为1
            }
            j = huffTree[j].parent;
        }
        cout << huffTree[i].ch << ":";
        for (int len = s.size() - 1; len >= 0; len--) { //s“从后往前”(反序)输出,即为编码
            cout << s[len];
            huffTree[i].code += s[len]; //保存编码
        }
        cout << endl;
    }
}

string HuffmanTree::Huff_Decode(Node huffTree[], int n, string s) {
    string temp = "", str = "";//str用来保存解码后的字符串
    for (int i = 0; i < s.size(); i++) {
        temp = temp + s[i];
        for (int j = 0; j < n; j++) {
            if (temp == huffTree[j].code) {
                str = str + huffTree[j].ch;
                temp = "";//赋为“空”
                break;
            }
        }
    }
    return str;
}

string HuffmanTree::unique(string str) {//去重
    string temp;
    temp.append(str, 0, 1);//初始
    for (int i = 1, j = 0; i < str.length(); i++) {
        for (j = 0; j < temp.length(); j++) {
            if (temp[j] == str[i])//判断在temp中是否已有元素与str[i]相同
                break;
        }
        if (j == temp.length())//若无重复,在temp尾处添加str[i]
            temp.append(str, i, 1);
    }
    return temp;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    string str, str2;
    cin >> str;
    HuffmanTree T;
    str2 = T.unique(str);
    sort(str2.begin(), str2.end());//对str2中的字符排序
    if (str2.size() == 1) { //如果str2只有一个元素(即str中所有元素都相同),则无法通过Select函数建树,单独考虑
        cout << str2 << ":" << 0 << endl;//编码为 0 ( 或 1)
        for (int i = 0; i < str.size(); ++i)  cout << 0;
        cout << endl;
        cout << str;//默认此时解码一定为本身,这里不经过 Huff_Decode解码函数,直接输出
    }
    else {
        int n = str2.size();
        Node* huffTree = new Node[2 * n - 1];
        for (int i = 0; i < str2.size(); ++i) {//计算权值(字符出现的频次)
            huffTree[i].weight = count(str.begin(), str.end(), str2[i]);
        }
        T.Huff_Tree(huffTree, str2, n);
        T.Huff_Code(huffTree, n);
        string s;
        for (int i = 0; i < str.size(); ++i) {
            for (int j = 0; j < str2.size(); ++j) {
                if (str2[j] == str[i]) {
                    cout << huffTree[j].code;//输出编码出来的密文
                    s += huffTree[j].code;//s用来储存密文
                }
            }
        }
        cout << endl;
        cout << T.Huff_Decode(huffTree, n, s);
    }
    return 0;
}
相关文章
|
2月前
|
存储 自然语言处理 Linux
探究C/C++编码世界:从字符编码到中文处理之艺(三)
探究C/C++编码世界:从字符编码到中文处理之艺
46 2
|
2月前
|
自然语言处理 C++
探究C/C++编码世界:从字符编码到中文处理之艺(二)
探究C/C++编码世界:从字符编码到中文处理之艺
41 2
|
2月前
|
存储 自然语言处理 程序员
探究C/C++编码世界:从字符编码到中文处理之艺(一)
探究C/C++编码世界:从字符编码到中文处理之艺
35 1
|
3月前
|
存储 算法 搜索推荐
【编码狂想】探索C++ STL:提升编程效率的强大工具集
【编码狂想】探索C++ STL:提升编程效率的强大工具集
31 0
|
3月前
|
机器学习/深度学习 算法 C语言
【编码狂想】深度探索C++编程之旅:“数组、字符串、函数与KMP算法解密“
【编码狂想】深度探索C++编程之旅:“数组、字符串、函数与KMP算法解密“
73 0
|
2月前
|
安全 编译器 C语言
MISRA C++ 、Google C++ 、AUTOSAR Adaptive Platform编码 C++ 规范总结
MISRA C++ 、Google C++ 、AUTOSAR Adaptive Platform编码 C++ 规范总结
104 1
|
2月前
|
存储 机器学习/深度学习 算法
深入探索数据压缩:哈夫曼编码与其同类技术的原理与C++ 实现
深入探索数据压缩:哈夫曼编码与其同类技术的原理与C++ 实现
53 0
|
10月前
|
编解码 Linux 开发工具
C++实现RTMP协议发送H.264编码及AAC编码的音视频,摄像头直播
C++实现RTMP协议发送H.264编码及AAC编码的音视频,摄像头直播
175 0
|
10月前
|
C++
C++实现对RGB图片进行编码
介绍了如何利用得到的RGB信息重新对RGB图片进行编码,以及对其他图片如BMP所得到的RGB信息进行编码从而得到*.jpg文件。
114 0
【C++要笑着学】编码的由来 | basic_string模板类 | string类的常用接口讲解 | 学会查文档(三)
好久不见!前段时间比较忙,更新频率有所减缓。好在现在快忙完了,我又有时间更文咯,还希望大伙能多多支持!我将会呈现出更多高质量的博客给大家!
78 1
【C++要笑着学】编码的由来 | basic_string模板类 | string类的常用接口讲解 | 学会查文档(三)