霍夫碼編碼(一種不等長,非前綴編碼方式)

霍夫曼編碼是一種不等長非前綴編碼方式,于1951年由MIT的霍夫曼提出。
用于對一串數字/符號編碼獲取最短的結果,獲取最大的壓縮效率。
特點:不等長非前綴

等長式編碼

等長編碼,意思是對出現的元素采用相同位數的序號進行標定,如下列所示:(這里我們采用三位)

假設有這樣一串數據:

編碼后的數據量:12 x 3bit=36bit.
思考:對5個數編碼沒必要每個數是同樣的長度,只要五個字符對應的五個編碼各自具有可區分性就行了。
非等長編碼就是對不同的字符進行不同長度的編碼

非等長式編碼

如下列所示,我們采用非等長編碼:

拿剛才說的字符串舉例:

編碼后的數據量是:3x2+1x5+2x3+41+14=25bit.
數據量減少了。
思考:如何確定哪種字符使用比較長的編碼,哪種字符使用比較短的編碼?
出現次數越多的字符我們使用更加短的編碼,出現次數越少的字符我們使用更加長的編碼。
現在可能又有疑問:為何不能像這樣,B=0,A=1,類似這樣,我們可以獲取更加短的編碼。
這里就要說到霍夫曼編碼的另外一個特性:非前綴編碼。

非前綴編碼

以下圖為例:

任何一個數據的編碼都不與其他數據的編碼的前綴重復。
如果B的編碼為1,則和其他編碼的前綴重復。
又如,C為11的話就和A、D、E的前綴重復了。
非前綴編碼的優點:
在編碼的時候其實和前綴編碼一樣,并沒有什么簡化的步驟。
但是在解碼的時候將會有不同的效果:
假設,我們現在有一串數據:

解碼得:
1110 110 1111 0 10 0 110 10 0 0 0 10
D A E B C B A C B B B C
已知碼表,對編碼后的信息進行解碼,不需要知道斷位信息,即可解碼。也就是說我們不需要知道哪幾個字符屬于同一個就可以進行解碼.

前綴編碼

假設編碼方式為如下。
前綴編碼
當獲取的數據串是:

11
在不知道斷位信息的前提下,我們是無法對這串數據進行編碼的。

霍夫曼編碼

霍夫曼編碼提供一種自動的方式獲取非前綴非等長的編碼,通過二叉樹進行編碼。

1)將信源符號的概率按減小的順序排隊。
2)把兩個最小的概率相加,并繼續這一步驟,始終將較高的概率分支放在右邊,直到最后變成概率1。
3)畫出由概率1處到每個信源符號的路徑,順序記下沿路徑的0和1,所得就是該符號的霍夫曼碼字。
4)將每對組合的左邊一個指定為0,右邊一個指定為1(或相反)。

例子講解:
1、計算每個字符出現次數

input出現次數
B10
A8
C3
D4
E5

2、把出現次數(概率)最小的兩個相加,并作為左右子樹,重復此過程,直到概率值為1
1
第一次:將概率最低值3和4相加,組合成7:
1
第二次:將最低值5和7相加,組合成12:
2
第三次:將8和10相加,組合成18:
3
第四次:將最低值12和18相加,結束組合:
4
3 將每個二叉樹的左邊指定為0,右邊指定為1
3
4 沿二叉樹頂部到每個字符路徑,獲得每個符號的編碼

output編碼
B11
A10
C010
D011
E00

霍夫曼編碼的缺陷

(1)哈夫曼編碼所形成的碼字不是復唯一的,但編碼效率是唯一的在對最小的兩個概率符號賦值時,可以規定為大的為“1”、小的為“0”,反之也可以。如果兩個符號的出現概率相等時,排列時無論哪個在前都是可以的,所以哈夫曼所構造的碼字不是唯一的,對于制同一個信息源,無論上述的前后順序如何排列,它的平均碼長是不會改變的,所以編碼效率是唯一的。
(2)只有當信息源各符號出現的概率很不平百均的時候,哈夫曼編碼的效果才明顯。
(3)哈夫曼編碼必須精確地統度計出原始文件中每個符號的出現頻率,如果沒有這些精確的統計,將達不到預期的壓縮效果。霍夫曼編通常要經過兩遍操作,第一遍進行統計,第二遍產生編碼,所以編碼速度相對慢。另外實現的電路復雜,各問種長度的編碼的譯碼過程也是較復雜的,因此解壓縮的過程也比較慢。
(4)哈夫曼編碼只能用整數來表示單個符號而不能用小數,這很大程度上限制了壓縮效果。
(5)哈夫曼所有位都是合在一起的,如果改動其中一位就可以答使其數據變得面目全非

編程實現

代碼摘自博客:霍夫曼編碼(Huffman Coding)

#include <stdio.h>
#include<stdlib.h>
#include<string>
#include <iostream>#define MAXBIT      100
#define MAXVALUE  10000
#define MAXLEAF     30
#define MAXNODE    MAXLEAF*2 -1typedef struct 
{int bit[MAXBIT];int start;
} HCodeType;        /* 編碼結構體 */
typedef struct
{int weight;int parent;int lchild;int rchild;char value;
} HNodeType;        /* 結點結構體 *//* 構造一顆哈夫曼樹 */
void HuffmanTree (HNodeType HuffNode[MAXNODE],  int n)
{ /* i、j: 循環變量,m1、m2:構造哈夫曼樹不同過程中兩個最小權值結點的權值,x1、x2:構造哈夫曼樹不同過程中兩個最小權值結點在數組中的序號。*/int i, j, m1, m2, x1, x2;/* 初始化存放哈夫曼樹數組 HuffNode[] 中的結點 */for (i=0; i<2*n-1; i++){HuffNode[i].weight = 0;//權值 HuffNode[i].parent =-1;HuffNode[i].lchild =-1;HuffNode[i].rchild =-1;HuffNode[i].value=' '; //實際值,可根據情況替換為字母  } /* end for *//* 輸入 n 個葉子結點的權值 */for (i=0; i<n; i++){printf ("Please input char of leaf node: ", i);scanf ("%c",&HuffNode[i].value);getchar();} /* end for */for (i=0; i<n; i++){printf ("Please input  weight of leaf node: ", i);scanf ("%d",&HuffNode[i].weight);getchar();} /* end for *//* 循環構造 Huffman 樹 */for (i=0; i<n-1; i++){m1=m2=MAXVALUE;     /* m1、m2中存放兩個無父結點且結點權值最小的兩個結點 */x1=x2=0;/* 找出所有結點中權值最小、無父結點的兩個結點,并合并之為一顆二叉樹 */for (j=0; j<n+i; j++){if (HuffNode[j].weight < m1 && HuffNode[j].parent==-1){m2=m1; x2=x1; m1=HuffNode[j].weight;x1=j;}else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1){m2=HuffNode[j].weight;x2=j;}} /* end for *//* 設置找到的兩個子結點 x1、x2 的父結點信息 */HuffNode[x1].parent  = n+i;HuffNode[x2].parent  = n+i;HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight;HuffNode[n+i].lchild = x1;HuffNode[n+i].rchild = x2;printf ("x1.weight and x2.weight in round %d: %d, %d\n", i+1, HuffNode[x1].weight, HuffNode[x2].weight);  /* 用于測試 */printf ("\n");} /* end for */} /* end HuffmanTree *///解碼 
void decodeing(char string[],HNodeType Buf[],int Num)
{int i,tmp=0,code[1024];int m=2*Num-1;char *nump;char num[1024];for(i=0;i<strlen(string);i++){if(string[i]=='0')num[i]=0;        elsenum[i]=1;                    } i=0;nump=&num[0];while(nump<(&num[strlen(string)])){tmp=m-1;while((Buf[tmp].lchild!=-1)&&(Buf[tmp].rchild!=-1)){if(*nump==0){tmp=Buf[tmp].lchild ;          } else tmp=Buf[tmp].rchild;nump++;} printf("%c",Buf[tmp].value);                                  }
}int main(void)
{HNodeType HuffNode[MAXNODE];            /* 定義一個結點結構體數組 */HCodeType HuffCode[MAXLEAF],  cd;       /* 定義一個編碼結構體數組, 同時定義一個臨時變量來存放求解編碼時的信息 */int i, j, c, p, n;char pp[100];printf ("Please input n:\n");scanf ("%d", &n);HuffmanTree (HuffNode, n);for (i=0; i < n; i++){cd.start = n-1;c = i;p = HuffNode[c].parent;while (p != -1)   /* 父結點存在 */{if (HuffNode[p].lchild == c)cd.bit[cd.start] = 0;elsecd.bit[cd.start] = 1;cd.start--;        /* 求編碼的低一位 */c=p;                    p=HuffNode[c].parent;    /* 設置下一循環條件 */} /* end while *//* 保存求出的每個葉結點的哈夫曼編碼和編碼的起始位 */for (j=cd.start+1; j<n; j++){ HuffCode[i].bit[j] = cd.bit[j];}HuffCode[i].start = cd.start;} /* end for *//* 輸出已保存好的所有存在編碼的哈夫曼編碼 */for (i=0; i<n; i++){printf ("%d 's Huffman code is: ", i);for (j=HuffCode[i].start+1; j < n; j++){printf ("%d", HuffCode[i].bit[j]);}printf(" start:%d",HuffCode[i].start);printf ("\n");}printf("Decoding?Please Enter code:\n");scanf("%s",&pp);decodeing(pp,HuffNode,n);getchar();return 0;
}

結果
Reference:

霍夫曼編碼(HuffmanCoding)
哈夫曼編碼和二進制編碼優缺點比較
《數字圖像處理PPT.李竹版》

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

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

相關文章

php調用shell腳本安全,從PHP調用的shell腳本問題

TLDR;我有一個shell腳本,從命令行運行時工作正常,但如果從PHP腳本中調用(通過Web訪問)則不行.在這兩種情況下,主叫用戶都是www-data.線路失敗是這樣的&#xff1a;openssl genrsa -des3 -out certs/$PCODE.key -passout env:PASSPHRASE 2048為什么會這樣&#xff1f;我該怎么調…

linux 運維基礎問題_Linux基礎能力問題和解答

linux 運維基礎問題This section contains Aptitude Questions and Answers on Linux Basics. 本節包含有關Linux基礎知識的 Aptitude問答。 1) There are the following statements that are given below, which of them are correct about Linux? Linux is system software…

JS 獲取瀏覽器信息,給出友情提示,避免部分兼容性問題

最近在做webform,瀏覽器兼容是個問題,這里我收集了一些獲取瀏覽器信息的資料,可以給一些用戶使用時,提示瀏覽器版本過低,讓升級版本用. 這樣會給開發的我們,省下很多用來調試兼容性的時間和精力. 本人就是這樣想的 ~  檢測瀏覽器及版本使用 JavaScript 檢測關于訪問者的瀏覽器…

兩欄 三欄的css

三欄格局 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns"http://www.w3.org/1999/xhtml" xml:lang"zh" lang"zh"><head pro…

06-機器學習(Haar+Adaboost實現人臉、人眼檢測)

機器學習是什么? 機器學習訓練樣本特征分類器&#xff0c;通過讓機器學習的方式&#xff0c;來達到某種功能的過程 深度學習是什么&#xff1f; 深度學習海量的學習樣本人工神經網絡 機器學習需要&#xff1a;樣本、特征、分類器、對訓練后的數據進行預測或檢驗 人臉樣本haar…

php xml表格形式輸出,PHP XML如何輸出nice格式

這里是代碼&#xff1a;$doc new DomDocument(1.0);// create root node$root $doc->createElement(root);$root $doc->appendChild($root);$signed_values array(a > eee, b > sd, c > df);// process one row at a timeforeach ($signed_values as $key &…

Opencv實戰【3】——圖像修復與圖像銳化(darling in the franxx)

目錄前言圖像修復圖像銳化darling in the franxx圖片總結前言 前天&#xff0c;在群里看見有人發了這張表情包&#xff1a; 感覺女主有點好看&#xff0c;然后問室友是啥番劇&#xff08;darling in the franxx&#xff09;&#xff0c;然后就去補番了&#xff0c;然后從晚上…

python 示例_Python date isoweekday()方法與示例

python 示例Python date.isoweekday()方法 (Python date.isoweekday() Method) date.isoweekday() method is used to manipulate objects of date class of module datetime. date.isoweekday()方法用于處理模塊日期時間的日期類的對象。 It uses a date class object and r…

07-機器學習(Hog+SVM實現小獅子識別)

一、SVM支持向量機 什么是SVM支持向量機&#xff1f; SVM支持向量機本質仍是一個分類器&#xff0c;其核心為尋求一個最優超平面最終實現分類&#xff0c;實現分類問題 在尋求超平面的時候有多種方式&#xff0c;可以使用若干條直線或曲線進行分類&#xff0c;這里使用的是直線…

Net Remoting基礎篇

一、Remoting基礎 什么是Remoting&#xff0c;簡而言之&#xff0c;我們可以將其看作是一種分布式處理方式。從微軟的產品角度來看&#xff0c;可以說Remoting就是DCOM的一種升 級&#xff0c;它改善了很多功能&#xff0c;并極好的融合到.Net平臺下。Microsoft .NET Remoting …

Maven3.0.5代理nexus

Nexus簡介 Nexus是Sonatype推出的強大Maven倉庫管理器產品&#xff0c;要比以前TSS上介紹的Artifactory要好使用的多&#xff0c;也是一個拆箱即用的Java App&#xff0c;內嵌Jetty容器和Java Wrapper做Windows服務&#xff0c;安裝簡單到解壓然后雙擊install即可。更詳細的幫助…

8253譯碼電路設計以及初始化編程講解

先驗知識回顧&#xff1a;知識點不清晰的時候可以查詢相關知識點。 https://blog.csdn.net/qq_42604176/article/details/105810973 需掌握的主要知識點 1、譯碼電路設計 2、初始化編程 例題1 在以 8086構成的最大方式系統中&#xff0c;有一片8254的端口地址分別為301H、3…

java安卓寫文件路徑,如何使用gradle作為構建系統,平臺Android配置Protobuf(Java)文件的輸出路徑?...

我正在努力解決以下問題&#xff1a;我有2個基于maven的java項目和1個基于gradle的Android項目 . 布局如下&#xff1a;Workspace/├── MavenProj1/├── MavenProj2/├── AndroidGradleProject1/├── Protos/所有這些的包結構很常見&#xff0c;比方說 com.example.* 所…

Java System類exit()方法及示例

系統類exit()方法 (System class exit() method) exit() method is available in java.lang package. exit()方法在java.lang包中可用。 exit() method is used to exit the currently running JVM (Java Virtual Machine). exit()方法用于退出當前正在運行的JVM(Java虛擬機)。…

基于圖像處理的數碼印花噴墨墨滴形狀規范的研究(Python+OpenCV+Mysql)

大體思路&#xff1a;由于墨滴的不同參數會對墨滴的形態產生一定的影響&#xff0c;故如果通過研究墨滴的形態則通過海量的數據就可以大概確定墨滴的各項參數指標的范圍。通過OpenCV對墨滴的噴出的形狀進行圖像處理&#xff0c;對墨滴圖像進行一系列的分析&#xff0c;通過一系…

ASP.NET 主題(Themes)FAQ

1、主題是什么 主題由一組元素組成&#xff1a;外觀、級聯樣式表 (CSS)、圖像和其他資源。主題將至少包含外觀。主題是在網站或 Web 服務器上的特殊目錄中定義的。主題是一組Web Control的屬性設置的集合&#xff0c;提供一種簡單的方法設置控件的樣式屬性。 主題只在Web Contr…

Head First HTML與CSS、XHTML++筆記(第四章 WEB鎮之旅 第五章 認識媒體)

第四章 鏈接&#xff08;詳解<a>元素&#xff09; 目標錨 在目標位置 <h2><a id"chai">contentTest</a></h2> 在需要鏈接位置 <a href"index.html#chai">See</a> 鏈接到自身的目標錨 <a href"#top"…

Opencv實戰【4】——圖片動漫化處理

博主聯系方式&#xff1a; QQ:1540984562 微信&#xff1a;wxid_nz49532kbh9u22 QQ交流群&#xff1a;750313950 目錄動漫化風格的特點處理手段代碼實現效果總結動漫化風格的特點 &#xff08;1&#xff09;動漫中的細節相對少&#xff1b; &#xff08;2&#xff09;動漫中的邊…

nextshort_Java掃描儀的nextShort()方法與示例

nextshort掃描器類的nextShort()方法 (Scanner Class nextShort() method) Syntax: 句法&#xff1a; public short nextShort();public short nextShort(int rad);nextShort() method is available in java.util package. nextShort()方法在java.util包中可用。 nextShort() …

php 生成css文件怎么打開,php生成html文件的多種步驟介紹

//定義日期函數functiongetdatetime(){$datetimegetdate();$strReturn$datetime["year"]."-";$strReturn$strReturn.$datetime["mon"]."-";$strReturn$strReturn.$datetime["mday"];return$strReturn;}//定義時間函數(文件名…