zoukankan      html  css  js  c++  java
  • 哈夫曼编码

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 //Huffman树的节点类
     7 typedef struct Node
     8 {
     9     char value;               //结点的字符值   
    10     int weight;               //结点字符出现的频度
    11     Node *lchild, *rchild;     //结点的左右孩子
    12 }Node;
    13 
    14 //自定义排序规则,即以vector中node结点weight值升序排序
    15 bool ComNode(Node *p, Node *q)
    16 {
    17     return p->weight<q->weight;
    18 }
    19 
    20 //构造Huffman树,返回根结点指针
    21 Node* BuildHuffmanTree(vector<Node*> vctNode)
    22 {
    23     while (vctNode.size()>1)                            //vctNode森林中树个数大于1时循环进行合并
    24     {
    25         sort(vctNode.begin(), vctNode.end(), ComNode);   //依频度高低对森林中的树进行升序排序
    26 
    27         Node *first = vctNode[0];    //取排完序后vctNode森林中频度最小的树根
    28         Node *second = vctNode[1];   //取排完序后vctNode森林中频度第二小的树根
    29         Node *merge = new Node;      //合并上面两个树
    30         merge->weight = first->weight + second->weight;
    31         merge->lchild = first;
    32         merge->rchild = second;
    33 
    34         vector<Node*>::iterator iter;
    35         iter = vctNode.erase(vctNode.begin(), vctNode.begin() + 2);    //从vctNode森林中删除上诉频度最小的两个节点first和second
    36         vctNode.push_back(merge);                                 //向vctNode森林中添加合并后的merge树
    37     }
    38     return vctNode[0];            //返回构造好的根节点
    39 }
    40 
    41 //用回溯法来打印编码
    42 void PrintHuffman(Node *node, vector<int> vctchar)
    43 {
    44     if (node->lchild == NULL && node->rchild == NULL)
    45     {//若走到叶子节点,则迭代打印vctchar中存的编码
    46         cout << node->value << ": ";
    47         for (vector<int>::iterator iter = vctchar.begin(); iter != vctchar.end(); iter++)
    48             cout << *iter;
    49         cout << endl;
    50         return;
    51     }
    52     else
    53     {
    54         vctchar.push_back(1);     //遇到左子树时给vctchar中加一个1
    55         PrintHuffman(node->lchild, vctchar);
    56         vctchar.pop_back();       //回溯,删除刚刚加进去的1
    57         vctchar.push_back(0);     //遇到左子树时给vctchar中加一个0
    58         PrintHuffman(node->rchild, vctchar);
    59         vctchar.pop_back();       //回溯,删除刚刚加进去的0
    60 
    61     }
    62 }
    63 
    64 int main()
    65 {
    66     cout << "************ Huffman编码问题 ***************" << endl;
    67     cout << "请输入要编码的字符,并以空格隔开(个数任意):" << endl;
    68     vector<Node*> vctNode;        //存放Node结点的vector容器vctNode
    69     char ch;                      //临时存放控制台输入的字符
    70     while ((ch = getchar()) != '
    ')
    71     {
    72         if (ch == ' ')continue;      //遇到空格时跳过,即没输入一个字符空一格空格
    73         Node *temp = new Node;
    74         temp->value = ch;
    75         temp->lchild = temp->rchild = NULL;
    76         vctNode.push_back(temp);  //将新的节点插入到容器vctNode中
    77     }
    78 
    79     cout << endl << "请输入每个字符对应的频度,并以空格隔开:" << endl;
    80     for (int i = 0; i<vctNode.size(); i++)
    81         cin >> vctNode[i]->weight;
    82 
    83     Node *root = BuildHuffmanTree(vctNode);   //构造Huffman树,将返回的树根赋给root
    84     vector<int> vctchar;
    85     cout << endl << "对应的Huffman编码如下:" << endl;
    86     PrintHuffman(root, vctchar);
    87 
    88     system("pause");
    89 }
  • 相关阅读:
    (Java实现) 洛谷 P1106 删数问题
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1553 数字反转(升级版)
    (Java实现) 洛谷 P1051 谁拿了最多奖学金
    (Java实现) 洛谷 P1051 谁拿了最多奖学金
    (Java实现) 洛谷 P1106 删数问题
    目测ZIP的压缩率
  • 原文地址:https://www.cnblogs.com/yuanshuang/p/5388895.html
Copyright © 2011-2022 走看看