>백엔드 개발 >PHP 튜토리얼 >허프만 인코딩이란 무엇입니까? PHP에서 허프만 인코딩 및 디코딩을 구현하는 방법은 무엇입니까?

허프만 인코딩이란 무엇입니까? PHP에서 허프만 인코딩 및 디코딩을 구현하는 방법은 무엇입니까?

不言
不言원래의
2018-07-26 15:37:321768검색

허프만 코딩이란? 허프만 코딩은 데이터 압축 알고리즘입니다. 일반적으로 사용되는 zip 압축의 핵심은 Huffman 인코딩이며, HTTP/에서는 Huffman 인코딩을 사용하여 HTTP 헤더를 압축합니다. 이 기사에서는 PHP에서 Huffman 인코딩 및 디코딩 구현 방법을 공유하겠습니다.

1. 허프만 인코딩

단어 개수

허프만 인코딩의 첫 번째 단계는 문서에서 각 문자의 발생 횟수를 계산하는 것입니다. PHP의 내장 함수 count_chars()는 다음과 같이 할 수 있습니다. a 허프만 트리

다음으로, 통계적 결과를 바탕으로 허프만 트리를 구성합니다. 구성 방법은 Wikipedia에 자세히 설명되어 있습니다. 다음은 PHP로 작성된 간단한 버전입니다.

$input = file_get_contents('input.txt');
$stat = count_chars($input, 1);

계산 후 $root는 허프만 트리의 루트 노드를 가리킵니다.

허프만 트리를 기반으로 코딩 사전 생성

허프만 트리를 사용하면 사전을 생성할 수 있습니다. 코딩의 경우 :

$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);

파일 쓰기

사전을 사용하여 파일 내용을 인코딩하고 파일에 씁니다. 허프만 인코딩을 파일에 작성할 때 주의할 점이 몇 가지 있습니다.

인코딩 사전을 작성하고 내용을 파일에 함께 작성한 후에는 경계를 구분할 수 없으므로 그들이 차지하는 바이트를 기록해야 합니다. PHP에서 제공하는 fwrite() 함수는 한 번에 8비트(1바이트) 또는 8비트의 정수배를 쓸 수 있습니다. 그러나 허프만 인코딩에서는 문자가 1비트로만 표현될 수 있으며, PHP는 파일에 1비트만 쓰는 작업을 지원하지 않습니다. 따라서 우리는 인코딩을 직접 연결해야 하며 매 8비트를 얻은 후에만 파일을 작성해야 합니다.

8비트를 얻을 때마다 쓰기

허프만 인코딩이란 무엇입니까? PHP에서 허프만 인코딩 및 디코딩을 구현하는 방법은 무엇입니까?두 번째 항목과 마찬가지로 최종 파일 크기는 8비트의 정수배가 되어야 합니다. 따라서 전체 인코딩의 크기가 8001비트인 경우 끝에 7개의 0을 추가해야 합니다

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);

2. 허프만 인코딩의 디코딩

허프만 인코딩 디코딩은 비교적 간단합니다. 먼저 인코딩 사전을 읽은 다음 그에 따라 사전에 원본 문자를 디코딩합니다. 디코딩 과정에서 주의해야 할 문제가 있습니다. 인코딩 과정에서 파일 끝에 여러 개의 0비트를 추가했기 때문에 이 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);

3. 테스트

허프만 인코딩 위키 페이지의 HTML 코드를 로컬에 저장하고 허프만 인코딩 테스트를 진행했습니다. 테스트 결과: 인코딩 전: 418,504바이트

인코딩 후: 280,127바이트

space. 원본 텍스트에 반복되는 내용이 많은 경우 허프만 인코딩으로 절약한 공간은 50% 이상에 달할 수 있습니다.

텍스트 내용 외에도 다음과 같은 바이너리 파일을 허프만 인코딩해 보겠습니다. f.lux 설치 프로그램, 실험 결과는 다음과 같습니다.

인코딩 전: 770,384바이트

인코딩 후: 773,076바이트

인코딩 후에는 사전을 저장할 때 더 많은 공간을 차지합니다. 추가 처리를 하지 않기 때문에 공간을 많이 차지하지 않습니다. 반면 바이너리 파일에서는 각 문자가 나타날 확률이 상대적으로 균일하여 허프만 코딩의 장점을 활용할 수 없습니다.

관련 권장사항:

php는 URL 매개변수를 인코딩하고 디코딩합니다

위 내용은 허프만 인코딩이란 무엇입니까? PHP에서 허프만 인코딩 및 디코딩을 구현하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.