Rumah pembangunan bahagian belakang tutorial php Huffman编码是什么?php中Huffman编码与解码的实现方法

Huffman编码是什么?php中Huffman编码与解码的实现方法

Jul 26, 2018 pm 03:37 PM

Huffman编码是什么?Huffman 编码是一种数据压缩算法。我们常用的 zip 压缩,其核心就是 Huffman 编码,还有在 HTTP/中,Huffman 编码被用于 HTTP 头部的压缩。这篇文章中我将给大家分享php中Huffman编码与解码的实现方法。

1. Huffman编码

字数统计

Huffman编码的第一步就是要统计文档中每个字符出现的次数,PHP的内置函数 count_chars() 就可以做到:

$input = file_get_contents('input.txt');
$stat = count_chars($input, 1);
Salin selepas log masuk

构造Huffman树

接下来根据统计结果构造Huffman树,构造方法在 Wikipedia 有详细的描述。这里用PHP写了一个简易版的:

$huffmanTree = [];foreach ($stat as $char => $count) {
    $huffmanTree[] = [        
    'k' => chr($char),        
    'v' => $count,        
    'left' => null,        
    'right' => null,
    ];
}// 构造树的层级关系,思想见wiki:https://zh.wikipedia.org/wiki/%E9%9C%8D%E5%A4%AB%E6%9B%BC%E7%BC%96%E7%A0%81$size = count($huffmanTree);for ($i = 0; $i !== $size - 1; $i++) {
    uasort($huffmanTree, function ($a, $b) {        
    if ($a['v'] === $b['v'])
     {            
     return 0;
        }        
        return $a[&#39;v&#39;] < $b[&#39;v&#39;] ? -1 : 1;
    });
    $a = array_shift($huffmanTree);
    $b = array_shift($huffmanTree);
    $huffmanTree[] = [        
    &#39;v&#39; => $a[&#39;v&#39;] + $b[&#39;v&#39;],        
    &#39;left&#39; => $b,        
    &#39;right&#39; => $a,
    ];
}
$root = current($huffmanTree);
Salin selepas log masuk

经过计算之后,$root 就会指向 Huffman 树的根节点

根据Huffman树生成编码字典

有了 Huffman 树,就可以生成用于编码的字典:

function buildDict($elem, $code = &#39;&#39;, &$dict) {    
if (isset($elem[&#39;k&#39;]))
 {
        $dict[$elem[&#39;k&#39;]] = $code;
    } else {
        buildDict($elem[&#39;left&#39;], $code.&#39;0&#39;, $dict);
        buildDict($elem[&#39;right&#39;], $code.&#39;1&#39;, $dict);
    }
}
$dict = [];
buildDict($root, &#39;&#39;, $dict);
Salin selepas log masuk

写文件

运用字典将文件内容进行编码,并写入文件。将Huffman编码写入文件的有几个注意的地方:

将编码字典和编码内容一起写入文件后,就没法区分他们的边界了,因此需要在文件开始写入他们各自占用的字节数

PHP提供的 fwrite() 函数一次能写入 8-bit(一个字节)或者是 8的整数倍个bit。但Huffman编码中,一个字符可能只使用 1-bit 表示,PHP不支持只往文件中写入 1-bit 这种操作。所以需要我们自行对编码进行拼接,每凑齐 8-bit 才写入文件。

8470638-ba24d5e1aee7ce30.png

每凑齐8-bit才写入

与第二条类似,最终形成的文件大小一定是 8-bit 的整数倍。所以如果整个编码的大小是 8001-bit的话,还要在末尾补上 7个 0

$dictString = serialize($dict);// 写入字典和编码各自占用的字节数
$header = pack(&#39;VV&#39;, strlen($dictString), strlen($input));
fwrite($outFile, $header);// 写入字典本身
fwrite($outFile, $dictString);// 写入编码的内容$buffer = &#39;&#39;;
$i = 0;while (isset($input[$i])) {
    $buffer .= $dict[$input[$i]];    
    while (isset($buffer[7])) {
        $char = bindec(substr($buffer, 0, 8));
        fwrite($outFile, chr($char));
        $buffer = substr($buffer, 8);
    }
    $i++;
}// 末尾的内容如果没有凑齐 8-bit,需要自行补齐
if (!empty($buffer))
 {
    $char = bindec(str_pad($buffer, 8, &#39;0&#39;));
    fwrite($outFile, chr($char));
}
fclose($outFile);
Salin selepas log masuk

2.Huffman编码的解码

Huffman编码的解码相对简单:先读取编码字典,然后根据字典解码出原始字符。

解码过程有个问题需要注意:由于我们在编码过程中,在文件末尾补齐了几个0-bit,如果这些 0-bit 在字典中恰巧是某个字符的编码时,就会造成错误的解码。

所以解码过程中,当已解码的字符数达到文档长度时,就要停止解码。

<?php
$content = file_get_contents(&#39;a.out&#39;);// 读出字典长度和编码内容长度
$header = unpack(&#39;VdictLen/VcontentLen&#39;, $content);
$dict = unserialize(substr($content, 8, $header[&#39;dictLen&#39;]));
$dict = array_flip($dict);
$bin = substr($content, 8 + $header[&#39;dictLen&#39;]);
$output = &#39;&#39;;
$key = &#39;&#39;;
$decodedLen = 0;
$i = 0;
while (isset($bin[$i]) && $decodedLen !== $header[&#39;contentLen&#39;]) {
    $bits = decbin(ord($bin[$i]));
    $bits = str_pad($bits, 8, &#39;0&#39;, STR_PAD_LEFT);    
    for ($j = 0; $j !== 8; $j++) {        // 每拼接上 1-bit,就去与字典比对是否能解码出字符
        $key .= $bits[$j];        
        if (isset($dict[$key]))
         {
            $output .= $dict[$key];
            $key = &#39;&#39;;
            $decodedLen++;            
            if ($decodedLen === $header[&#39;contentLen&#39;])
             {             
                break;
            }
        }
    }
    $i++;
}echo $output;
Salin selepas log masuk

3.试验

我们将Huffman编码Wiki页 的HTML代码保存到本地,进行Huffman编码测试,试验结果:

编码前: 418,504 字节

编码后: 280,127 字节

空间节省了 33%,如果原文的重复内容较多,Huffman编码节省的空间可以达到 50% 以上.

除了文本内容,我们再尝试将一个二进制文件进行Huffman编码,比如 f.lux的安装程序,试验结果如下:

编码前: 770,384 字节

编码后: 773,076 字节

编码后反而占用了更大的空间,一方面是由于我们存储字典时,并没有做额外的处理,占用了不少空间。另一方面,二进制文件中,各个字符出现的概率相对比较平均,无法发挥Huffman编码的优势。

相关推荐:

php对URL传参进行编码和解码解析

Atas ialah kandungan terperinci Huffman编码是什么?php中Huffman编码与解码的实现方法. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Curl dalam PHP: Cara Menggunakan Pelanjutan PHP Curl dalam API REST Curl dalam PHP: Cara Menggunakan Pelanjutan PHP Curl dalam API REST Mar 14, 2025 am 11:42 AM

Pelanjutan URL Pelanggan PHP (CURL) adalah alat yang berkuasa untuk pemaju, membolehkan interaksi lancar dengan pelayan jauh dan API rehat. Dengan memanfaatkan libcurl, perpustakaan pemindahan fail multi-protokol yang dihormati, php curl memudahkan execu yang cekap

12 skrip sembang php terbaik di codecanyon 12 skrip sembang php terbaik di codecanyon Mar 13, 2025 pm 12:08 PM

Adakah anda ingin memberikan penyelesaian segera, segera kepada masalah yang paling mendesak pelanggan anda? Sembang langsung membolehkan anda mempunyai perbualan masa nyata dengan pelanggan dan menyelesaikan masalah mereka dengan serta-merta. Ia membolehkan anda memberikan perkhidmatan yang lebih pantas kepada adat anda

Terangkan konsep pengikatan statik lewat dalam PHP. Terangkan konsep pengikatan statik lewat dalam PHP. Mar 21, 2025 pm 01:33 PM

Artikel membincangkan pengikatan statik lewat (LSB) dalam PHP, yang diperkenalkan dalam Php 5.3, yang membolehkan resolusi runtime kaedah statik memerlukan lebih banyak warisan yang fleksibel. Isu: LSB vs polimorfisme tradisional; Aplikasi Praktikal LSB dan Potensi Perfo

Jelaskan JSON Web Tokens (JWT) dan kes penggunaannya dalam PHP API. Jelaskan JSON Web Tokens (JWT) dan kes penggunaannya dalam PHP API. Apr 05, 2025 am 12:04 AM

JWT adalah standard terbuka berdasarkan JSON, yang digunakan untuk menghantar maklumat secara selamat antara pihak, terutamanya untuk pengesahan identiti dan pertukaran maklumat. 1. JWT terdiri daripada tiga bahagian: header, muatan dan tandatangan. 2. Prinsip kerja JWT termasuk tiga langkah: menjana JWT, mengesahkan JWT dan muatan parsing. 3. Apabila menggunakan JWT untuk pengesahan di PHP, JWT boleh dijana dan disahkan, dan peranan pengguna dan maklumat kebenaran boleh dimasukkan dalam penggunaan lanjutan. 4. Kesilapan umum termasuk kegagalan pengesahan tandatangan, tamat tempoh, dan muatan besar. Kemahiran penyahpepijatan termasuk menggunakan alat debugging dan pembalakan. 5. Pengoptimuman prestasi dan amalan terbaik termasuk menggunakan algoritma tandatangan yang sesuai, menetapkan tempoh kesahihan dengan munasabah,

Ciri -ciri Keselamatan Rangka Kerja: Melindungi Kelemahan. Ciri -ciri Keselamatan Rangka Kerja: Melindungi Kelemahan. Mar 28, 2025 pm 05:11 PM

Artikel membincangkan ciri -ciri keselamatan penting dalam rangka kerja untuk melindungi daripada kelemahan, termasuk pengesahan input, pengesahan, dan kemas kini tetap.

Bagaimana cara menghantar permintaan pos yang mengandungi data JSON menggunakan perpustakaan php curl? Bagaimana cara menghantar permintaan pos yang mengandungi data JSON menggunakan perpustakaan php curl? Apr 01, 2025 pm 03:12 PM

Menghantar data JSON menggunakan perpustakaan Curl PHP dalam pembangunan PHP, sering kali perlu berinteraksi dengan API luaran. Salah satu cara biasa ialah menggunakan perpustakaan curl untuk menghantar post ...

Menyesuaikan/Memperluas Rangka Kerja: Cara Menambah Fungsi Custom. Menyesuaikan/Memperluas Rangka Kerja: Cara Menambah Fungsi Custom. Mar 28, 2025 pm 05:12 PM

Artikel ini membincangkan menambah fungsi khusus kepada kerangka kerja, memberi tumpuan kepada pemahaman seni bina, mengenal pasti titik lanjutan, dan amalan terbaik untuk integrasi dan debugging.

See all articles