【C++】哈夫曼編碼:高效的壓縮算法

哈夫曼編碼:高效的壓縮算法

什么是哈夫曼編碼?

哈夫曼編碼是一種用于數據壓縮的無損編碼方法,由David A. Huffman于1952年提出。它利用了字符出現頻率的不均勻性,通過構建最優前綴碼,能夠有效減少數據的冗余,從而實現高效的壓縮。

哈夫曼編碼的基本原理

哈夫曼編碼的核心思想是使用較短的編碼表示高頻字符,較長的編碼表示低頻字符。通過這種方式,可以顯著減少總體編碼長度。具體步驟如下:

  1. 統計頻率

    • 統計每個字符在數據中的出現頻率。
  2. 構建優先隊列

    • 將每個字符及其頻率作為一個節點,構建一個優先隊列(最小堆)。
  3. 構建哈夫曼樹

    • 從優先隊列中取出兩個頻率最小的節點,構建一個新的節點,其頻率為兩個節點頻率之和。
    • 將新節點重新插入隊列中,重復該過程,直到隊列中只剩下一個節點,即哈夫曼樹的根節點。
  4. 生成編碼

    • 從根節點開始,為每個左子節點分配“0”,右子節點分配“1”,遞歸進行直到葉子節點,葉子節點的路徑即為該字符的哈夫曼編碼。
詳細步驟示例

假設我們需要對字符串“abbccdd”進行編碼,具體步驟如下:

統計頻率:

a: 1
b: 2
c: 2
d: 2

構建優先隊列:

初始化優先隊列:[(1, ‘a’), (2, ‘b’), (2, ‘c’), (2, ‘d’)]

構建哈夫曼樹:

取出頻率最小的兩個節點(1, ‘a’)和(2, ‘b’),合并為新節點(3, ‘ab’)。
插入新節點后,隊列變為:[(2, ‘c’), (2, ‘d’), (3, ‘ab’)]
取出頻率最小的兩個節點(2, ‘c’)和(2, ‘d’),合并為新節點(4, ‘cd’)。
插入新節點后,隊列變為:[(3, ‘ab’), (4, ‘cd’)]
取出頻率最小的兩個節點(3, ‘ab’)和(4, ‘cd’),合并為新節點(7, ‘abcd’),形成最終的哈夫曼樹:

      (7)0/     \1(3)      (4)0/ \1  0/   \1
(1) (2) (2) (2)|   |   |   |a   b   c   d
生成編碼:

a: 00
b: 01
c: 10
d: 11

哈夫曼編碼的優缺點

優點

  • 高效壓縮:對于具有較大頻率差異的數據,哈夫曼編碼能顯著降低編碼長度。
  • 無損壓縮:能夠完全恢復原始數據。

缺點

  • 靜態性:經典哈夫曼編碼需要先掃描數據統計頻率,對于動態數據或實時數據不太適用。
  • 復雜性:構建哈夫曼樹需要額外的存儲空間和計算資源。
哈夫曼編碼的應用

哈夫曼編碼廣泛應用于各種數據壓縮場景,例如:

  • 文件壓縮:如ZIP、RAR等文件格式。
  • 多媒體編碼:如JPEG、MP3等格式中的數據壓縮。
  • 通信系統:用于高效數據傳輸。
代碼實現

下面是一個用C++實現的簡單哈夫曼編碼示例:

#include <iostream>
#include <queue>
#include <unordered_map>
#include <vector>using namespace std;struct Node {char ch;int freq;Node *left, *right;Node(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {}
};// 比較函數,用于優先隊列
struct Compare {bool operator()(Node* l, Node* r) {return l->freq > r->freq;}
};void buildCodes(Node* root, string str, unordered_map<char, string> &huffmanCode) {if (!root) return;// 葉子節點if (!root->left && !root->right) {huffmanCode[root->ch] = str;}buildCodes(root->left, str + "0", huffmanCode);buildCodes(root->right, str + "1", huffmanCode);
}void huffmanCoding(string text) {// 統計頻率unordered_map<char, int> freq;for (char ch : text) {freq[ch]++;}// 構建優先隊列priority_queue<Node*, vector<Node*>, Compare> pq;for (auto pair : freq) {pq.push(new Node(pair.first, pair.second));}// 構建哈夫曼樹while (pq.size() != 1) {Node *left = pq.top(); pq.pop();Node *right = pq.top(); pq.pop();int sum = left->freq + right->freq;Node *node = new Node('\0', sum);node->left = left;node->right = right;pq.push(node);}// 根節點Node* root = pq.top();// 生成編碼unordered_map<char, string> huffmanCode;buildCodes(root, "", huffmanCode);// 輸出編碼cout << "哈夫曼編碼:\n";for (auto pair : huffmanCode) {cout << pair.first << " " << pair.second << "\n";}// 編碼文本string encodedString = "";for (char ch : text) {encodedString += huffmanCode[ch];}cout << "編碼后的字符串:\n" << encodedString << "\n";
}int main() {string text = "abbccdd";huffmanCoding(text);return 0;
}

※ 如果文章對你有幫助的話,可以點贊收藏!!謝謝支持

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/16294.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/16294.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/16294.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Flutter仿照微信實現九宮格頭像

一、效果圖 2、主要代碼 import dart:io; import dart:math;import package:cached_network_image/cached_network_image.dart; import package:flutter/material.dart;class ImageGrid extends StatelessWidget {final List<String> imageUrls; // 假設這是你的圖片URL…

關于Iterator 和ListIterator的詳解

1.Iterator Iterator的定義如下&#xff1a; public interface Iterator<E> {} Iterator是一個接口&#xff0c;它是集合的迭代器。集合可以通過Iterator去遍歷集合中的元素。Iterator提供的API接口如下&#xff1a; forEachRemaining(Consumer<? super E> act…

VS2022通過C++網絡庫Boost.Asio創建一個簡單的同步TCP服務器和客戶端

Boost.Asio是一個用于網絡和異步編程的C庫。它提供了一種跨平臺的方式來處理網絡編程和異步操作&#xff0c;使開發人員能夠創建高性能的網絡應用程序&#xff0c;asio幾乎支持所有你能夠想到的網絡協議&#xff0c;比如tcp、udp、ip、http、icmp等&#xff0c;C通過asio庫可以…

找出第 K 大的異或坐標值

問題 給你一個二維矩陣 matrix 和一個整數 k &#xff0c;矩陣大小為 m x n 由非負整數組成。 矩陣中坐標 (a, b) 的 值 可由對所有滿足 0 < i < a < m 且 0 < j < b < n 的元素 matrix[i][j]&#xff08;下標從 0 開始計數&#xff09;執行異或運算得到。…

淺談網絡通信(1)

文章目錄 一、認識一些網絡基礎概念1.1、ip地址1.2、端口號1.3、協議1.4、協議分層1.5、協議分層的2種方式1.5.1、OSI七層模型1.5.2、TCP/IP五層模型[!]1.5.2.1、TCP/IP五層協議各層的含義及功能 二、網絡中數據傳輸的基本流程——封裝、分用2.1、封裝2.2、分用2.2.1、5元組 三…

基于大模型和RAG技術實現的開源項目

基于大模型和RAG技術實現的開源項目 為解決大模型的不足&#xff0c;使用RAG技術增強大模型生成內容的針對性和可讀性能力&#xff0c;有很多不錯的開源項目。例如下面的項目。 1 ragflow 優點&#xff1a;可以對文檔和知識庫進行管理&#xff0c;構建不同的知識庫&#xff…

python冰雹序列的探索與編程實現

新書上架~&#x1f447;全國包郵奧~ python實用小工具開發教程http://pythontoolsteach.com/3 歡迎關注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目錄 一、冰雹序列的奧秘 二、編程實現冰雹序列 三、測試與驗證 四、總結與展望 一、冰雹序列的…

整理好了!2024年最常見 20 道 Redis面試題(八)

上一篇地址&#xff1a;整理好了&#xff01;2024年最常見 20 道 Redis面試題&#xff08;七&#xff09;-CSDN博客 十五、Redis 的性能調優有哪些方法&#xff1f; Redis的性能調優是一個多方面的工作&#xff0c;涉及到硬件、配置、代碼層面的優化等多個方面。以下是一些常…

openEuler 22.03 LTS SP3源碼編譯部署OpenStack-Caracal

openEuler 22.03 LTS SP3源碼編譯部署OpenStack-Caracal 說明機器詳情安裝操作系統注意事項基礎準備Controller節點 && Compute節點 && Block節點關閉防火墻關閉selinux設置靜態IP更新安裝前準備Controller節點 && Compute節點 && Block節點設…

第十課,while循環

一&#xff0c;認識循環是什么 循環普遍存在于日常生活中&#xff0c;同樣&#xff0c;在程序中&#xff0c;循環功能也是至關重要的基礎功能。 當程序需要重復執行某一段代碼&#xff0c;利用循環可以輕松完成工作 例如我要你打印100次上課&#xff0c;直接寫100次print&…

python調用阿里云通義千問(q-wen-max)API-只能總結pdf文檔內容

文章目錄 通義千問插件PDF解析插件調用案例通義千問插件 Dashscope插件功能能夠使得大模型的生成內容與外部三方應用結合,使得模型生成的內容更加準確和豐富,模型將擁有更好的生成能力。您也可以通過開發自定義插件,來使得模型生成更符合您預期的結果。 使用插件功能,大模…

電子閱覽室在管理時需注意什么

關于如今的絕大多數人來說&#xff0c;想必都聽說過“電子閱覽室”這一概念。它首要運用在校園中&#xff0c;給學生們供給愈加豐厚的常識儲藏。它也是一個獨立的局域網&#xff0c;在校園網絡中作為重要的一個組成部分而存在。但是&#xff0c;一個好的電子閱覽室是需求滿意運…

LORA學習筆記3——訓練參數

訓練步長 Step&#xff08;步&#xff09;:模型訓練時ai模型會根據標注生成一個圖片&#xff0c;并與學習圖片進行對比&#xff0c;通過對比的結果調整嵌入向量。這樣的一個流程就被稱為“一步”。 如果一個訓練集中有50張圖片&#xff0c;每張圖片設定為要訓練10次&#xff…

CCF20231201——倉庫規劃

CCF20231201——倉庫規劃 代碼如下&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int n,m,a[1001][11],b[1001]{0};cin>>n>>m;for(int i1;i<n;i){for(int j1;j<m;j)cin>>a[i][j];}for(int i1;i<n;i){bool foundfals…

設計模式在芯片驗證中的應用——模板方法

一、模板方法 模板方法(Template Method)設計模式是一種行為設計模式&#xff0c; 它在父類中定義了一個功能的框架&#xff0c; 允許子類在不修改結構的情況下重寫功能的特定步驟。也就是模板方法定義了一組有序執行的操作&#xff0c;將一些步驟的實現留給子類&#xff0c;同…

把自己的垃圾代碼發布到官方中央倉庫

參考博客&#xff1a;將組件發布到maven中央倉庫-CSDN博客 感謝這位博主。但是他的步驟有漏缺&#xff0c;相對進行補充 訪問管理頁面 網址&#xff1a;Maven Central 新注冊賬號&#xff0c;或者使用github快捷登錄&#xff0c;建議使用github快捷登錄 添加命名空間 注意&…

連接mysql的java代碼

要在Java中連接MySQL數據庫,你需要以下幾個步驟: 導入MySQL JDBC驅動:在項目中添加MySQL JDBC驅動的依賴。如果你使用的是Maven,可以在pom.xml中添加依賴;如果使用的是Gradle,可以在build.gradle中添加依賴;如果不使用構建工具,需要手動下載驅動并添加到項目中。 編寫J…

【Linux】進程通信實戰 —— 進程池項目

送給大家一句話: 沒有一顆星&#xff0c;會因為追求夢想而受傷&#xff0c;當你真心渴望某樣東西時&#xff0c;整個宇宙都會來幫忙。 – 保羅?戈埃羅 《牧羊少年奇幻之旅》 &#x1f3d5;?&#x1f3d5;?&#x1f3d5;?&#x1f3d5;?&#x1f3d5;?&#x1f3d5;? &a…

flink cdc mysql整理與總結

文章目錄 一、業務中常見的需要數據同步的場景CDC是什么FlinkCDC是什么CDC原理為什么是FlinkCDC業務場景flink cdc對應flink的版本 二、模擬案例1.阿里云flink sql2.開源flink sql(單機模式)flink 安裝安裝mysql3.flink datastream 三、總結 提示&#xff1a;以下是本篇文章正文…

mac中文件夾怎么顯示.git隱藏文件

1. 打開終端應用程序&#xff0c;然后進入到包含.git文件夾的目錄&#xff0c;可以使用以下命令來顯示隱藏文件和文件夾&#xff1a; defaults write com.apple.finder AppleShowAllFiles YES 2. 然后重啟 Finder&#xff1a; killall Finder