c++14 STL 对排序输入进行高效霍夫曼编码 | 贪婪算法(Efficient Huffman Coding for Sorted Input | Greedy Algo)

 排序输入的高效霍夫曼编码 示例图

建议先阅读下面的文章:

 c语言:c语言 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)_霍夫曼的贪婪c语言-CSDN博客

c++:c++ 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)_霍夫曼的贪婪算法设计核心代码-CSDN博客

c#:C# 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)-CSDN博客

c++ STL:c++ STL 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)-CSDN博客

java:java 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)-CSDN博客

python:python 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)-CSDN博客

javascript:JavaScript 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)-CSDN博客

        上面讨论的算法的时间复杂度是 O(nLogn)。如果我们知道给定的数组是排好序的(按频率非递减顺序),我们可以在 O(n) 时间内生成霍夫曼码。以下是针对已排序输入的 O(n) 算法。

1.创建两个空队列。

2.为每个唯一字符创建一个叶节点,并按频率非递减顺序将其入队到第一个队列。最初第二个队列是空的。

3.通过检查两个队列的前面,使两个频率最小的节点出队。重复以下步骤两次 
        1. 如果第二个队列为空,则从第一个队列出队。

2. 如果第一个队列为空,则从第二个队列出队。 
        3. 否则,比较两个队列的前面,并使最小的节点出队。 
        4.创建一个新的内部节点,其频率等于两个节点频率之和。将第一个出队节点设为其左子节点,将第二个出队节点设为右子节点。将此节点入队到第二个队列。
5.重复步骤 3 和 4,直到队列中有多个节点。剩下的节点就是根节点,树就完成了。 

示例代码: 

// Clean c++ stl code to generate huffman codes if the array
// is sorted in non-decreasing order
#include <bits/stdc++.h>
using namespace std;
 
// Node structure for creating a binary tree
struct Node {
    char ch;
    int freq;
    Node* left;
    Node* right;
    Node(char c, int f, Node* l = nullptr,
         Node* r = nullptr)
        : ch(c)
        , freq(f)
        , left(l)
        , right(r){};
};
 
// Find the min freq node between q1 and q2
Node* minNode(queue<Node*>& q1, queue<Node*>& q2)
{
    Node* temp;
 
    if (q1.empty()) {
        temp = q2.front();
        q2.pop();
        return temp;
    }
 
    if (q2.empty()) {
        temp = q1.front();
        q1.pop();
        return temp;
    }
 
    if (q1.front()->freq < q2.front()->freq) {
        temp = q1.front();
        q1.pop();
        return temp;
    }
    else {
        temp = q2.front();
        q2.pop();
        return temp;
    }
}
 
// Function to print the generated huffman codes
void printHuffmanCodes(Node* root, string str = "")
{
    if (!root)
        return;
    if (root->ch != '$') {
        cout << root->ch << ": " << str << '\n';
        return;
    }
 
    printHuffmanCodes(root->left, str + "0");
    printHuffmanCodes(root->right, str + "1");
 
    return;
}
 
// Function to generate huffman codes
void generateHuffmanCode(vector<pair<char, int> > v)
{
    if (!v.size())
        return;
 
    queue<Node*> q1;
    queue<Node*> q2;
 
    for (auto it = v.begin(); it != v.end(); ++it)
        q1.push(new Node(it->first, it->second));
 
    while (!q1.empty() or q2.size() > 1) {
        Node* l = minNode(q1, q2);
        Node* r = minNode(q1, q2);
        Node* node = new Node('$', l->freq + r->freq, l, r);
        q2.push(node);
    }
 
    printHuffmanCodes(q2.front());
    return;
}
 
int main()
{
    vector<pair<char, int> > v
        = { { 'a' , 5 },  { 'b' , 9 },  { 'c' , 12 },
            { 'd' , 13 }, { 'e' , 16 }, { 'f' , 45 } };
    generateHuffmanCode(v);
    return 0;

输出: 

f: 0 
c: 100 
d: 101 
a: 1100 
b: 1101 
e: 111

时间复杂度: O(n)
        如果输入未排序,则需要先对其进行排序,然后才能通过上述算法进行处理。排序可以使用堆排序或合并排序来完成,两者都在 Theta(nlogn) 中运行。因此,对于未排序的输入,总体时间复杂度变为 O(nlogn)。 
辅助空间: O(n)

  • 19
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用C++20的STL迭代器对输入进行排序的完整代码: ```c++ #include <iostream> #include <vector> #include <algorithm> #include <iterator> int main() { std::vector<int> nums; // 通过迭代器读入数字 std::cout << "请输入数字,以-1结束输入:" << std::endl; std::istream_iterator<int> input_iter(std::cin); std::istream_iterator<int> eof; std::copy(input_iter, eof, std::back_inserter(nums)); // 对数字进行排序 std::sort(nums.begin(), nums.end()); // 输出排序后的结果 std::cout << "排序后的结果为:" << std::endl; std::ostream_iterator<int> output_iter(std::cout, " "); std::copy(nums.begin(), nums.end(), output_iter); std::cout << std::endl; return 0; } ``` 在上面的代码中,我们首先定义了一个 `std::vector<int>` 容器 `nums`,然后通过迭代器从标准输入流中读入数字,并将其加入到容器中。 接着,我们使用STL中的 `std::sort` 算法对容器中的数字进行排序。 最后,我们使用迭代器将排序后的结果输出到标准输出流中。 需要注意的是,我们在读入数字时,使用了 `std::istream_iterator<int>` 迭代器来从标准输入流中读入数字,这个迭代器会自动读取下一个整数并返回。在读入结束后,我们使用 `std::istream_iterator<int>()` 来创建一个“空”的迭代器,表示输入流已经结束。在将数字输出时,我们使用了 `std::ostream_iterator<int>` 迭代器来将数字输出到标准输出流中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值