首頁 php教程 php手册 基于静态huffman编码的压缩

基于静态huffman编码的压缩

Jun 06, 2016 pm 07:31 PM
壓縮 基於 編碼 靜態

名词解释:哈夫曼编码(HuffmanCoding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。该方法依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。 实现过程: 1.计算每个字符在字符串中出现的频率作为构建h

名词解释:哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。该方法依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。

实现过程:

1.计算每个字符在字符串中出现的频率作为构建huffman树的权重

2.构建huffman树

3.建立每个字符对应的编码表

4.重建字符串编码,既压缩字符串

5.解压时根据先前的huffman树和字符位长度还原字符串
    <?php   
    /**
    基于静态huffman编码的压缩[PHP语言实现]
    author:        lajabs
    email:        aGl0dHlvQGdtYWlsLmNvbQ==

    本文以PHP作为描述语言较详细讲解huffman树原理及应用
    因保证程序可读性,故不做优化.

    */



    class huffman
    {
            /**
             * 压缩入口
             * $str:待压缩的字符串
             */
            public function encode($str)
            {
                    $len=strlen($str);
                    //计算每个字符权重值(出现的频度)<这边可以做成概率表>
                    for($i=0;$i<$len;$i++)        $array[ord($str{$i})]++;

                    $HuffmanArray=array();
                    asort($array);
                    /**
                     * 构造huffman树,时间复杂度O(nlogn)
                     * 选择两个使用频率较小<字符在字符串中出现的次数>的结点合并生成出一个树
                     */
                    while ($item1 = each($array))
                    {
                            $item2 = each($array);
                            //构建huffman树
                            $this->creat_tree($item1,$item2,$array,$HuffmanArray);
                            //反复排序<优化这步可在构造树时用插入排序算法完成>
                            asort($array);
                    }


                    $HuffmanArray=array_shift($HuffmanArray);
                    //构建编码表<这步可优化为构建树时一同生成>
                    $tab=null;
                    $code_tab=$this->creat_tab($HuffmanArray,$tab);
                    //压缩&转换整个字符串为二进制表达式
                    $binary=null;
                    for($i=0;$i<$len;$i++)        $binary.=$tab[ord($str{$i})];        
                    //转化为压缩后的字符串
                    $code=$this->encode_bin($binary);
                    //静态huffman编码算法压缩后需保留huffman树
                    return array('tree'=>$HuffmanArray,'len'=>strlen($binary),'code'=>$code);
            }

            /**
             * 解压缩入口
             * $huffman:解压所使用的huffman树
             * $str:被压缩的字符
             * $blen:压缩前的位长度
             */
            public function decode($huffman,$str,$blen)
            {
                    $len=strlen($str);
                    $binary=null;
                    //将编码解为二进制表达式
                    for($i=0;$i<$len;$i++)        
                    $binary.=str_pad(base_convert(ord($str{$i}),10,2),8,'0',STR_PAD_LEFT);
                    //去除补码
                    $binary=substr($binary,0,$blen);
                    //从hufman树中配比相应的编码
                    return $this->decode_tree($binary,$huffman,$huffman);
            }

            /**
             * 将压缩后的二进制表达式再转为字符串
             * $binary:二进制表达式字串
             */
            private function encode_bin($binary)
            {
                    $len=strlen($binary);
                    //二进制转字符需要整8位,不足8位补0
                    $blen=$len+8-$len%8;
                    $binary=str_pad($binary,$blen,'0');
                    $encode=null;
                    //每8位转为一个字符
                    for($i=7;$i<$blen;$i+=8)
                    {
                            $frag=substr($binary,$i-7,8);
                            $encode.=chr(base_convert($frag,2,10));
                    }
                    return $encode;
            }

            /**
             * 构造huffman树,使用贪婪算法选择最小的两个元素作为树的子节点
             * $item1:权重最小的元素1
             * $item2:权重次小的元素2
             * $array:所有字符出现次数表<权重表>
             * $HuffmanArray:保存生成的huffman树结构
             */
            private function creat_tree($item1,$item2,&$array,&$HuffmanArray)
            {
                    list($k,$v)=$item1;
                    list($k2,$v2)=$item2;
                    //假设当前树的左右节点为空节点
                    $c1=$k;
                    $c2=$k2;
                    //判断两个元素若为树则直接作为节点并入主树
                    if(isset($HuffmanArray[$k2]))
                    {
                            $c2=$HuffmanArray[$k2];        
                            unset($HuffmanArray[$k2]);
                    }
                    if(isset($HuffmanArray[$k]))
                    {
                            $c1=$HuffmanArray[$k];
                            unset($HuffmanArray[$k]);
                    }
                    //设置树结点权值
                    $array[$k2]=$v+$v2;                                                        
                    //合并节点后删除元素
                    unset($array[$k]);
                    //合并到huffman树中
                    $HuffmanArray[$k2]=array(0=>$c1,1=>$c2);        
            }


            /**
             * 广度优先遍历树,得到所有原字符对应的二进制表达式<01010...>
             * $tree:已经构建好的huffman树
             * $tab:编码表,保存所有字符对应的编码
             * $a0:左遍历树的路径<11010...>
             * $a1:右遍历树的路径
             */
            private function creat_tab($tree,&$tab,$a0=null,$a1=null)
            {
                    if($tree==null) return;
                    //遍历左右子树
                    foreach($tree as $node=>$ctree)
                    {
                            if(is_array($ctree))
                            {
                                    //判断未到达叶子节点时再向下遍历
                                    $this->creat_tab($ctree,$tab,$a0.$node,$a1.$node);
                            }
                            else
                            {
                                    //遍历到叶子节点<原字符ascii码>时的所有路径,既二进制表达式,下同
                                    $tab[$ctree]=${'a'.$node}.$node;
                            }
                    }
            }

            /**
             * 使用进制表达式深度优先遍历树,0为左子树,1为右子树,而到根节点,即为二进制表达式所指向的原字符
             * $binary:二进制表达式字串
             * $huffman:huffman树
             * $tree:当前所遍历的子树
             * $i:指向二进制表达式字串的<指针>
             * $code:解码后的字符串
             */
            private function decode_tree($binary,$huffman,$tree,$i=0,$code=null)
            {
                    $lr=$binary{$i};
                    //遍历完成
                    if($lr==null) return $code;
                    //判断是否到根节点,根节点既为二进制表达式对应的原字符ascii码
                    if(is_array($tree[$lr]))
                    {
                            //继续向下遍历子树
                            return $this->decode_tree($binary,$huffman,$tree[$lr],$i+1,$code);
                    }
                    else
                    {
                            //将二进制表达式解码为原字符
                            $code.=chr($tree[$lr]);
                            return $this->decode_tree($binary,$huffman,$huffman,$i+1,$code);
                    }
            }
    }
    ?>
登入後複製
    $str='
    In computer science and information theory, Huffman coding is an entropy encoding algorithm used for lossless data compression. The term refers to the use of a variable-length code table for encoding a source symbol (such as a character in a file) where the variable-length code table has been derived in a particular way based on the estimated probability of occurrence for each possible value of the source symbol. It was developed by David A. Huffman while he was a Ph.D. student at MIT, and published in the 1952 paper "A Method for the Construction of Minimum-Redundancy Codes".
    ';

    $huffman=new huffman();
    $obj=$huffman->encode($str);
    echo '压缩前的编码长度:',strlen($str),"\n";
    echo '压缩后的编码:',"\n";
    var_dump($obj['code']);
    echo '解压后的字符:',$huffman->decode($obj['tree'],$obj['code'],$obj['len']);
登入後複製
压缩前的编码长度:587压缩后的编码:string(330) "sp閉h颚?6鵞+王d挓吷s霒zk洚磗脎|t?*?;娳9蹴??>楏4O3 5 F凣rRuJ解压后的字符:In computer science and information theory, Huffman coding is an entropy encoding algorithm used for lossless data compression. The term refers to the use of a variable-length code table for encoding a source symbol (such as a character in a file) where the variable-length code table has been derived in a particular way based on the estimated probability of occurrence for each possible value of the source symbol. It was developed by David A. Huffman while he was a Ph.D. student at MIT, and published in the 1952 paper "A Method for the Construction of Minimum-Redundancy Codes".
登入後複製
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何在 Windows 11 上啟用或停用記憶體壓縮功能 如何在 Windows 11 上啟用或停用記憶體壓縮功能 Sep 19, 2023 pm 11:33 PM

使用Windows11上的記憶體壓縮,即使RAM量有限,您的裝置也會窒息運作。在本文中,我們將向您展示如何在Windows11上啟用或停用記憶體壓縮。什麼是記憶體壓縮?記憶體壓縮是一種在將資料寫入RAM之前壓縮資料的功能,從而在其上提供更多儲存空間。當然,儲存在實體記憶體中的更多資料轉化為更快的系統運作和更好的整體效能。此功能在Windows11中預設為啟用,但如果它以某種方式未處於活動狀態,您可以停用或重新啟用它。如何在Windows11中啟用記憶體壓縮?按一下搜尋欄,鍵入powershell,然後從結果中單

7-zip最大壓縮率設定,7zip如何壓縮到最小 7-zip最大壓縮率設定,7zip如何壓縮到最小 Jun 18, 2024 pm 06:12 PM

發現某下載網站下載的壓縮包,解壓縮後再打包會比原來的壓縮包大一些,小的幾十Kb的差別,大的幾十Mb的差別,如果上傳到雲盤或付費空間,文件少無所謂,文件多的話,大大的增加儲存成本。特意研究了下,有需要的可以藉鏡。壓縮等級:9-極限壓縮字典大小:256或384,字典越壓縮越慢,256MB之前壓縮率差異較大,384MB後壓縮率無差別單字大小:最大273參數:f=BCJ2,測試加參數壓縮率會高一些

知識圖譜:大模型的理想搭檔 知識圖譜:大模型的理想搭檔 Jan 29, 2024 am 09:21 AM

大型語言模式(LLM)具有產生流暢和連貫文字的能力,為人工智慧的對話、創意寫作等領域帶來了新的前景。然而,LLM也存在一些關鍵限制。首先,它們的知識僅限於從訓​​練資料中辨識出的模式,缺乏對世界的真正理解。其次,推理能力有限,不能進行邏輯推理或從多個資料來源融合事實。面對更複雜、更開放的問題時,LLM的回答可能變得荒謬或矛盾,被稱為「幻覺」。因此,儘管LLM在某些方面非常有用,但在處理複雜問題和真實世界情境時,仍存在一定的限制。為了彌補這些差距,近年來出現了檢索增強生成(RAG)系統,其核心思想是

常見的幾種編碼方式 常見的幾種編碼方式 Oct 24, 2023 am 10:09 AM

常見的編碼方式有ASCII編碼、Unicode編碼、UTF-8編碼、UTF-16編碼、GBK編碼等。詳細介紹:1、ASCII編碼是最早的字符編碼標準,使用7位二進制數表示128個字符,包括英文字母、數字、標點符號以及控製字符等;2、Unicode編碼是一種用於表示世界上所有字元的標準編碼方式,它為每個字元分配了一個唯一的數字碼點;3、UTF-8編碼等等。

減小win10錄影檔大小的建議 減小win10錄影檔大小的建議 Jan 04, 2024 pm 12:05 PM

許多的小夥伴都需要錄影畫面進行辦公室或傳輸文件,但是有時候會出現文件過大的問題製造了很多麻煩,下面就給大家帶來了文件過大的解決方法,一起看看吧。 win10錄影檔太大怎麼辦:1.下載軟體格式工廠來進行壓縮檔。下載位址>>2、進入主頁面,點選「影片-MP4」選項。 3、在轉換格式頁面中點選“新增檔案”,選擇要壓縮的MP4檔案。 4、點擊頁面“輸出配置”,透過輸出品質來壓縮檔案。 5、下拉配置清單選擇「低品質和大小」點選「確定」。 6、點選「確定」完成影片檔案的導入。 7.點選「開始」進行轉換。 8.完成後即可

深入解析C語言中static關鍵字的作用與用法 深入解析C語言中static關鍵字的作用與用法 Feb 20, 2024 pm 04:30 PM

深入解析C語言中static關鍵字的功能和用法在C語言中,static是一種非常重要的關鍵字,它可以被用於函數、變數和資料類型的定義。使用static關鍵字可以改變物件的連結屬性、作用域和生命週期,以下就來詳細解析一下static關鍵字在C語言中的作用和用法。 static變數與函數:在函數內部使用static關鍵字定義的變數稱為靜態變量,它具有全域生命週

wps怎麼壓縮資料夾打包發送 wps怎麼壓縮資料夾打包發送 Mar 20, 2024 pm 12:58 PM

辦公人員在工作中使用wps軟體進行操作的頻率特別地多,有時一天會輸入多個文件,然後發送給領導或發送到指定位置,那麼wps軟體如何壓縮文件夾打包發送呢,下面小編就教大家這個操作步驟。首先,將要傳送的文件和資料夾整理到同一個資料夾中。如果有很多文件,最好將每個文件命名,這樣在發送時更容易識別。  第二步,這個時候點擊這個大的資料夾,然後點擊滑鼠右鍵。選擇“新增到壓縮檔案”。  第三步,這個時候軟體會自動幫我們打包我們的文件,選項“壓縮到XX.zip”,這個zip就是打包的格式,然後點擊立即壓縮。 

winrar 64位元-winrar怎麼解壓縮? winrar 64位元-winrar怎麼解壓縮? Mar 18, 2024 pm 12:55 PM

WinRAR是一款功能強大的壓縮檔案管理工具,提供了豐富的功能和易於使用的介面。 WinRAR64位元版本特別針對64位元作業系統進行了最佳化,能夠更好地利用系統資源和效能。接下來就請小編為大家介紹一下winrar64位元以及解答一下winrar怎麼解壓縮吧!一、winrar64位元是什麼軟體WinRAR是一款功能強大的壓縮套件管理器。這款軟體可用於備份您的數據,縮減電子郵件附件的大小,解壓縮從Internet上下載的RAR、ZIP及其它文件,並且可以新建RAR及ZIP格式的文件。目前最新WINRAR版本為Wi

See all articles