PHP 는 Huff man 인 코딩/디 코딩 의 예제 코드 를 실현 합 니 다.
본 고 는 PHP 로 Huffman 인 코딩 과 디 코딩 을 실천 하고 자 합 니 다.
1.인 코딩
글자 수 통계
Huffman 인 코딩 의 첫 번 째 단 계 는 문서 에 있 는 모든 문자 가 나타 나 는 횟수 를 통계 하 는 것 입 니 다.PHP 의 내장 함수 countchars()에서 할 수 있 습 니 다:
$input = file_get_contents('input.txt');
$stat = count_chars($input, 1);
구조 Huffman 나무다음은 통계 결과 에 따 르 면 허 프 맨 나 무 를 구성 하고 구조 방법 은 위 키 백과 에서 상세 하 게 설명 되 어 있다.여기에 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['v'] < $b['v'] ? -1 : 1;
});
$a = array_shift($huffmanTree);
$b = array_shift($huffmanTree);
$huffmanTree[] = [
'v' => $a['v'] + $b['v'],
'left' => $b,
'right' => $a,
];
}
$root = current($huffmanTree);
계산 을 통 해$root 는 Huffman 나무의 뿌리 노드 를 가리 킬 것 입 니 다.Huffman 트 리 에 따라 인 코딩 사전 생 성
Huffman 트 리 가 있 으 면 인 코딩 에 사용 할 사전 을 만 들 수 있 습 니 다.
function buildDict($elem, $code = '', &$dict) {
if (isset($elem['k'])) {
$dict[$elem['k']] = $code;
} else {
buildDict($elem['left'], $code.'0', $dict);
buildDict($elem['right'], $code.'1', $dict);
}
}
$dict = [];
buildDict($root, '', $dict);
서 류 를 쓰다사전 을 사용 하여 파일 내용 을 인 코딩 하고 파일 에 기록 합 니 다.Huffman 인 코딩 을 파일 에 기록 하 는 데 몇 가지 주의 할 점 이 있 습 니 다.
인 코딩 사전 과 인 코딩 내용 을 함께 파일 에 쓰 면 경 계 를 구분 할 수 없 기 때문에 각각 사용 하 는 바이트 수 를 파일 에 쓰기 시작 해 야 합 니 다.
PHP 에서 제공 하 는 fwrite()함 수 는 한 번 에 8-bit(한 바이트)또는 8 의 정수 배 bit 를 기록 할 수 있 습 니 다.그러나 Huffman 인 코딩 에서 한 문 자 는 1-bit 만 사용 할 수 있 습 니 다.PHP 는 파일 에 1-bit 만 쓰 는 것 을 지원 하지 않 습 니 다.그래서 우 리 는 스스로 인 코딩 을 맞 추고 8-bit 를 맞 출 때마다 파일 을 써 야 한다.
8 비트 씩 모 아서 쓰 는 거 예요.
제2 조 와 유사 하 게 최종 적 으로 형 성 된 파일 의 크기 는 반드시 8-bit 의 정수 배 이다.그래서 전체 인 코딩 의 크기 가 8001-bit 라면 끝 에 0 7 개 를 채 워 야 합 니 다.
$dictString = serialize($dict);
//
$header = pack('VV', strlen($dictString), strlen($input));
fwrite($outFile, $header);
//
fwrite($outFile, $dictString);
//
$buffer = '';
$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, '0'));
fwrite($outFile, chr($char));
}
fclose($outFile);
디 코딩Huffman 인 코딩 의 디 코딩 은 상대 적 으로 간단 합 니 다.인 코딩 사전 을 읽 은 다음 사전 에 따라 원본 문 자 를 디 코딩 합 니 다.
디 코딩 과정 에서 주의해 야 할 문제 가 있 습 니 다.인 코딩 과정 에서 파일 끝 에 0-bit 를 몇 개 보 정 했 기 때문에 0-bit 가 사전 에서 마침 특정한 문자 의 인 코딩 일 때 잘못된 디 코딩 을 할 수 있 습 니 다.
따라서 디 코딩 과정 에서 디 코딩 된 문자 수가 문서 길이 에 이 르 렀 을 때 디 코딩 을 중지 해 야 합 니 다.
<?php
$content = file_get_contents('a.out');
//
$header = unpack('VdictLen/VcontentLen', $content);
$dict = unserialize(substr($content, 8, $header['dictLen']));
$dict = array_flip($dict);
$bin = substr($content, 8 + $header['dictLen']);
$output = '';
$key = '';
$decodedLen = 0;
$i = 0;
while (isset($bin[$i]) && $decodedLen !== $header['contentLen']) {
$bits = decbin(ord($bin[$i]));
$bits = str_pad($bits, 8, '0', STR_PAD_LEFT);
for ($j = 0; $j !== 8; $j++) {
// 1-bit,
$key .= $bits[$j];
if (isset($dict[$key])) {
$output .= $dict[$key];
$key = '';
$decodedLen++;
if ($decodedLen === $header['contentLen']) {
break;
}
}
}
$i++;
}
echo $output;
테스트Huff man 인 코딩 위 키 페이지 의 HTML 코드 를 로 컬 에 저장 하여 Huff man 인 코딩 테스트 를 진행 합 니 다.시험 결과:
인 코딩 전:418,504 바이트
인 코딩 후:280,127 바이트
공간 은 33%를 절약 했다.만약 에 원문의 중복 내용 이 비교적 많 으 면 Huffman 인 코딩 이 절약 하 는 공간 은 50%이상 에 이 를 수 있다.
텍스트 내용 을 제외 하고 우 리 는 바 이 너 리 파일 을 Huffman 인 코딩 을 시도 합 니 다.예 를 들 어f.lux 설치 프로그램시험 결 과 는 다음 과 같 습 니 다.
인 코딩 전:770,384 바이트
인 코딩 후:773,076 바이트
인 코딩 후에 오히려 더 큰 공간 을 차지 했다.한편 으로 는 우리 가 사전 을 저장 할 때 별도의 처 리 를 하지 않 아 많은 공간 을 차지 했다.다른 한편,바 이 너 리 파일 에서 각 문자 가 나타 날 확률 이 상대 적 으로 평균 적 이어서 Huffman 인 코딩 의 장점 을 발휘 할 수 없습니다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
laravel에 yo에서 angularJs&coffeescript를 사용할 수 있도록 한다.먼저 yo 명령을 사용할 수 있어야하므로 아래에서 설치 global에 설치한 곳에서 laravel의 프로젝트 루트로 이동. 클라이언트 코드를 관리하는 디렉토리를 만들고 이동합니다. 클라이언트 환경 만들기 이것으로 히...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.