1. 程式人生 > >Huffman對字串進行無失真壓縮示例

Huffman對字串進行無失真壓縮示例

今天遇到一個問題,簡要來說就是輸入一串字串,對其進行無失真壓縮,儘量做到壓縮原始資料量。最先考慮到的方法是Huffman編碼,將其實現過程簡要描述。

第一步,輸入一串字串。

clear all;
clc;
%% 輸入待處理字串
text = 'aaaabbbbbbbbbccbbbcccaaaaaaaaaaaaaaaaaabccaab';
fprintf('原文為:\n');
disp(text);

第二步,計算字串出現的字元個數與每個字元出現的概率。

text_unique = unique(text);
N = length(text_unique);
p = zeros(1,N);
for i = 1:length(text)
    for j = 1:N
        if(strcmp(text(i), text_unique(j)) == 1)
            p(j) = p(j)+1;
            break;
        end
    end
end
p = p/length(text);

第三步,根據概率計算huffman碼錶。生成原理不具體介紹,請自行百度。

%% 3.huffman碼錶確定
[code_list, L_av] = Huffman(p);
for i = 1:length(code_list)
    Huff_tab{i,1} = strtrim(code_list(i,:));
    Huff_tab{i,2} = text_unique(i);
end
fprintf('huffman 碼錶:\n');
disp(Huff_tab);

主函式Huffman的實現過程為:

function [h,l]=Huffman(p);
%HUFFMAN 	Huffman code generator
%[h,l]=huffman(p), Huffman code generator returns h the Huffman code matrix,
%                  and l the average codeword length for a source with probability vector p. 
%p=[0.4,0.2,0.2,0.1,0.1];
if length(find(p<0))~=0,
  error('Not a prob. vector, negative component(s)')
end
if abs(sum(p)-1)>10e-10,
  error('Not a prob. vector, components do not add up to 1')
end
n=length(p);
q=p;
m=zeros(n-1,n);
for i=1:n-1
  [q,l]=sort(q);
  m(i,:)=[l(1:n-i+1),zeros(1,i-1)];
  q=[q(1)+q(2),q(3:n),1];
end
for i=1:n-1
  c(i,:)=blanks(n*n);
end
c(n-1,n)='0';
c(n-1,2*n)='1';
for i=2:n-1
  c(n-i,1:n-1)=c(n-i+1,n*(find(m(n-i+1,:)==1))...
  -(n-2):n*(find(m(n-i+1,:)==1)));
  c(n-i,n)='0';
  c(n-i,n+1:2*n-1)=c(n-i,1:n-1);
  c(n-i,2*n)='1';
  for j=1:i-1
    c(n-i,(j+1)*n+1:(j+2)*n)=c(n-i+1,...
    n*(find(m(n-i+1,:)==j+1)-1)+1:n*find(m(n-i+1,:)==j+1));
  end
end
for i=1:n
  h(i,1:n)=c(1,n*(find(m(1,:)==i)-1)+1:find(m(1,:)==i)*n);
  l1(i)=length(find(abs(h(i,:))~=32));
end
l=sum(p.*l1);
end

第四步,對輸入的字串進行編碼。

%% 4.將原文按碼錶進行編碼
enc_stream = [];
for i = 1:length(text)
    for j = 1:length(Huff_tab)
        if strcmp(text(i),Huff_tab{j,2})
            enc_stream = [enc_stream Huff_tab{j,1}];
            break;
        end
    end
end
fprintf('編碼結果為:\n');
disp(enc_stream);

第五步,對已編碼的二進位制序列進行解碼。

%% 5. 解壓
dec_stream = [];
I = [];
for i = 1:length(enc_stream)
    I = [I enc_stream(i)];
    for j = 1:length(Huff_tab)
        if strncmp(I, Huff_tab{j,1}, length(Huff_tab{j,1}))
            dec_stream = [dec_stream, Huff_tab{j, 2}];
            I = [];
            break;
        end
    end
end
fprintf('解碼結果為:\n');
disp(dec_stream);

處理結果為:

原文為:
aaaabbbbbbbbbccbbbcccaaaaaaaaaaaaaaaaaabccaab
huffman 碼錶
    '1'     'a'
    '01'    'b'
    '00'    'c'

編碼結果為:
111101010101010101010100000101010000001111111111111111110100001101
解碼結果為:
aaaabbbbbbbbbccbbbcccaaaaaaaaaaaaaaaaaabccaab

當然,也可以隨機生成字串統計huffman編碼的壓縮效率~~