C++ implementation uses Huffman coding method to realize the coding and decoding of communication characters (Huffman tree)

Topic: Use Huffman coding method to realize the coding and decoding of communication characters

Effect picture:

  • Enter the original string code to implement HuffmanTree
    Insert picture description here
  • Enter weights to implement HuffmanTree
    Insert picture description here
  • You can enter numbers, characters, spaces, and symbols at the same time

Insert picture description here

Ideas:

  • ①: First, in order to construct HuffmanTree, we need to process the input character weights. Here, since the main input method is input string, the corresponding function is used to calculate the weight of each character or directly input There are two ways for the weight of each character, and the corresponding processing methods are slightly different, but they are generally the same. I defined a double type weight array to store the weight of the character, and then defined a code array to store Each non-repeated character can solve the problem that when the user enters a string, even if there are a large number of repeated characters, the correct weight can be calculated. After the complete weight is obtained, we can start to build HuffmanTree.
  • ②First, we establish the corresponding number of HuffmanTree nodes according to the size of the code array, and at the same time initialize these nodes, and then we establish a priority queue q of the HuffmanTree node type, and proceed from small to large according to the weight of the node Internal sorting, so as to prepare for our next formal construction of HuffmanTree. Every time we take out the first two elements in q and merge them, we realize that each merged node is the node with the smallest weight. Merge, and then we put the merged node of the two nodes into the q queue again, and loop until there is only one element root node left in q, so that a HuffmanTree is constructed.
  • ③After the HuffmanTree is constructed, we can use the recursive function to traverse the HuffmanTree. The purpose of this is to print the encoding of each character. At the same time, we can also simulate the HuffmanTree tree to print the weight of each node, so You can see the internal construction of HuffmanTree more intuitively.
  • ④The decoding process only needs to traverse the HuffmanTree tree according to the input ciphertext, starting from the root node and the first bit of the ciphertext, if the current bit is '0', the current node changes from the root node to the root node If the current bit is '1', then the current node will change from the root node to the right node of the root node, so until the root node has no left and right nodes, we will save the characters in this node After printing out, the decoding of a character is realized. If you want to continue decoding, you only need to update the current node back to the original root node.

Code:

#include <stdio.h>
#include<windows.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
using namespace std;
vector<char> code;
double weight[256];
int n;    
typedef struct HuffTree
{
    
    
    string code;
    char symbol;
    double weight;
    HuffTree* lchild;
    HuffTree* rchild;
} Node,*Nodeptr;
struct cmp
{
    
    
    bool operator()(Nodeptr & a, Nodeptr & b)
    {
    
    
        return a->weight > b->weight;
    }
};
priority_queue<Nodeptr, vector<Nodeptr>, cmp>q;
void codework()
{
    
    
    cout << "----------欢迎使用霍夫曼树---------" << endl;
    cout << "请选择输入字符串原码或者输入权值:" << endl;
    cout << "1.输入原码 2.输入权值" << endl;
    int x;
    cin >> x;
    char ch=getchar();
    system("cls");
    switch (x)
    {
    
    
    case 1:
        {
    
    
        string s;
        cout << "请输入原码:";
        getline(cin, s);
        for (int i = 0; i < s.size(); i++)
        {
    
    
            if (count(code.begin(), code.end(), s[i]) == 0)
                code.push_back(s[i]);
            weight[s[i]]++;
        }
        }
        break;
    case 2:
        {
    
    
            int num;
            cout << "请输入要输入多少个字符:";
            cin >> num;
            for (int i = 0; i < num; i++)
            {
    
    
                getchar();
                char x;
                double y;
                cout << "请输入第" << i + 1 << "个字符" ;
                x = getchar();
                cout << "请输入第" << i + 1 << "个字符的权值";
                cin >> y;
                if (count(code.begin(), code.end(), x) == 0)
                code.push_back(x);
                weight[x]= y;
            }
           
        }
        break;
    }
}
void PrintHuffmanTree(Nodeptr root)
{
    
    
    cout << root->weight;
    if (root->lchild != NULL || root->rchild != NULL)
    {
    
    
        cout << "(";
        PrintHuffmanTree(root->lchild);
        cout << ",";
        PrintHuffmanTree(root->rchild);
        cout << ")";
    }
}
Nodeptr CreatHuffmanTree()
{
    
    
    codework();
    n = code.size();
    for (int i = 0; i <n; i++)
    {
    
    
        Nodeptr CurNode = new Node;
        CurNode->symbol = code[i];
        CurNode->weight = weight[code[i]];
        CurNode->lchild = NULL;
        CurNode->rchild = NULL;
        q.push(CurNode);
    }
    for (int i = 1; i <= n - 1; i++)
    {
    
    
        Nodeptr x1 = q.top();
        q.pop();
        Nodeptr x2 = q.top();
        q.pop();
        cout << "第" << i<< "次: 取出的左节点x1权值为" << (double)x1->weight << "   取出的右节点x2权值为:" << (double)x2->weight <<" 它们的父节点权值为:"<< (double)(x1->weight + x2->weight) << endl;//zrz 2020.5.20
        Nodeptr NewNode = new Node;
        NewNode->symbol = 0;
        NewNode->weight = x1->weight + x2->weight;
        NewNode->lchild = x1;
        NewNode->rchild = x2;
        q.push(NewNode);
    }
     PrintHuffmanTree(q.top());
     cout << endl;
     return q.top();
}
void Coding(Nodeptr root,string code)
{
    
    
    if (root->lchild == NULL && root->rchild == NULL)
    {
    
    
        root->code = code;
        cout << root->symbol << "的编码为:" << root->code << endl;
        return;
    }
    if (root->lchild != NULL)
    {
    
    
        code +='0';
        Coding(root->lchild, code);
        code = code.substr(0, code.size() - 1);
    }
    if (root->rchild != NULL)
    {
    
    
        code += '1';
        Coding(root->rchild, code);
        code = code.substr(0, code.size() - 1);
    }

}
void Decodeing(Nodeptr root)
{
    
    
    string s, Ciphertext, Plaintext;
    cout << "请输入要解码的字符串:";
    cin >> s;
    Nodeptr temp = root;
    for (int i = 0; i < s.size(); i++)
    {
    
    
        
        if (s[i] == '0')
        {
    
    
            if (temp->lchild != NULL)
            {
    
    
                Ciphertext += '0';
                temp = temp->lchild;
            }
        }
        else if (s[i] == '1')
        {
    
    
            Ciphertext += '1';
            if (temp->rchild != NULL)
            {
    
    
                temp = temp->rchild;
            }
        }
        if (temp->lchild == NULL && temp->rchild == NULL)
        {
    
    
            Ciphertext += ' ';
            Plaintext += temp->symbol;
            temp = root;
        }
    }
    for (int i = 0; i < Ciphertext.size(); i++)
        cout << Ciphertext[i];
    cout << endl;
    for (int i = 0; i < Plaintext.size(); i++)
        cout << Plaintext[i];
    cout << endl;
}
void DestroyHuffmanTree(Nodeptr root)
{
    
    
     if (root->lchild != NULL)
         DestroyHuffmanTree(root->lchild);
     if (root->rchild != NULL)
         DestroyHuffmanTree(root->rchild);
     delete(root);
}
int main()
{
    
    
    Node* root= CreatHuffmanTree();
    Coding(root, "");
    Decodeing(root);
    DestroyHuffmanTree(root);
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_43663263/article/details/106253163