前言
在網(wǎng)上看了好多 , 都是對香農(nóng)進(jìn)行編碼的案例 , 卻沒有 進(jìn)行解碼的操作 , 今天就來補(bǔ)齊這個(gè)欠缺文章來源:http://www.zghlxwxcb.cn/news/detail-476321.html
效果截圖如下
文章來源地址http://www.zghlxwxcb.cn/news/detail-476321.html
代碼解析
text = '你好'; % 待編碼的文本
- 定義一個(gè)字符串類型的變量text,其值為’你好’。
[encoded, decoded, avgCodeLength, efficiency] = shannonCoding(text);
- 調(diào)用函數(shù)shannonCoding對文本信息進(jìn)行編碼,并將編碼、解碼、平均碼長和編碼效率作為四個(gè)返回值保存到變量encoded, decoded, avgCodeLength和efficiency中。
disp('編碼結(jié)果:');
disp(encoded);
disp('解碼結(jié)果:');
disp(decoded);
disp('平均碼長:');
disp(avgCodeLength);
disp('編碼效率:');
disp(efficiency);
- 打印輸出編碼結(jié)果、解碼結(jié)果、平均碼長和編碼效率。
function [encoded, decoded, avgCodeLength, efficiency] = shannonCoding(text)
- 定義一個(gè)名為shannonCoding的函數(shù),輸入?yún)?shù)為待編碼的文本字符串text。輸出參數(shù)為編碼結(jié)果encoded、解碼結(jié)果decoded、平均碼長avgCodeLength和編碼效率efficiency。
symbols = unique(text);
freq = zeros(size(symbols));
for i = 1:length(symbols)
freq(i) = sum(text == symbols(i));
end
freq = freq / numel(text);
- 對于字符串text中所有不同的字符,使用unique()函數(shù)提取出來并存到symbols數(shù)組中,然后計(jì)算它們在字符串text中的出現(xiàn)頻率。具體來說,利用for循環(huán)遍歷symbols數(shù)組中的每一個(gè)字符,并計(jì)算其在字符串text中出現(xiàn)的次數(shù),最后將頻率存儲到freq數(shù)組中。最后,將freq數(shù)組中的每個(gè)元素除以總的字符數(shù)numel(text),即可得到每個(gè)字符的頻率。
cumProb = cumsum(freq);
- 計(jì)算符號累計(jì)概率(按照符號出現(xiàn)概率從大到小排列)。
codeTable = cell(length(symbols), 2);
for i = 1:length(symbols)
codeTable{i, 1} = symbols(i);
codeTable{i, 2} = ''; % 初始化編碼為空
end
- 初始化編碼表codeTable,用cell數(shù)組表示。codeTable的行數(shù)等于symbols中不同字符的個(gè)數(shù),每行有兩個(gè)元素:第一個(gè)是字符本身,第二個(gè)是該字符的編碼(最開始為空字符串)。
codeTable = buildCodeTable(codeTable, cumProb, 1, '');
- 調(diào)用函數(shù)buildCodeTable遞歸地構(gòu)建Huffman編碼表。
encoded = '';
for i = 1:numel(text)
symbol = text(i);
index = find(strcmp(codeTable(:, 1), symbol));
code = codeTable{index, 2};
encoded = [encoded, code];
end
- 遍歷文本text中的每個(gè)字符,找到對應(yīng)的Huffman編碼,最終將所有字符的編碼串聯(lián)起來,存儲在變量encoded中。
decoded = '';
code = '';
for i = 1:length(encoded)
code = [code, encoded(i)];
index = -1;
for j = 1:length(codeTable)
if strcmp(codeTable{j, 2}, code)
index = j;
break;
end
end
if index >= 0
decoded = [decoded, codeTable{index, 1}];
code = '';
end
end
- 解碼過程,將encoded按照長度依次取出一部分,逐個(gè)檢查編碼表codeTable中是否有對應(yīng)的碼。如果有,則對應(yīng)的字符添加到decoded中,并清空code。
codeLengths = cellfun(@length, codeTable(:, 2));
avgCodeLength = sum(codeLengths .* freq);
- 計(jì)算平均碼長,將每個(gè)字符的編碼長度乘以其在文本中的頻率,最后相加即可。
efficiency = 1 ./ avgCodeLength;
- 計(jì)算編碼效率,用單位1表示所需的二進(jìn)制位數(shù),所以編碼效率是1除以平均碼長。這里使用了向量化操作,相當(dāng)于計(jì)算每個(gè)碼字所需的二進(jìn)制位數(shù)之和再除以總的碼字個(gè)數(shù)。
end
- 函數(shù)定義結(jié)束。
完整代碼
text = '你好'; % 待編碼的文本
[encoded, decoded, avgCodeLength, efficiency] = shannonCoding(text);
disp('編碼結(jié)果:');
disp(encoded);
disp('解碼結(jié)果:');
disp(decoded);
disp('平均碼長:');
disp(avgCodeLength);
disp('編碼效率:');
disp(efficiency);
function [encoded, decoded, avgCodeLength, efficiency] = shannonCoding(text)
% 計(jì)算字符頻率
symbols = unique(text);
freq = zeros(size(symbols));
for i = 1:length(symbols)
freq(i) = sum(text == symbols(i));
end
freq = freq / numel(text);
% 計(jì)算累積概率
cumProb = cumsum(freq);
% 構(gòu)建編碼表
codeTable = cell(length(symbols), 2);
for i = 1:length(symbols)
codeTable{i, 1} = symbols(i);
codeTable{i, 2} = ''; % 初始化編碼為空
end
% 遞歸構(gòu)建編碼表
codeTable = buildCodeTable(codeTable, cumProb, 1, '');
% 編碼
encoded = '';
for i = 1:numel(text)
symbol = text(i);
index = find(strcmp(codeTable(:, 1), symbol));
code = codeTable{index, 2};
encoded = [encoded, code];
end
% 解碼
decoded = '';
code = '';
for i = 1:length(encoded)
code = [code, encoded(i)];
index = -1;
for j = 1:length(codeTable)
if strcmp(codeTable{j, 2}, code)
index = j;
break;
end
end
if index >= 0
decoded = [decoded, codeTable{index, 1}];
code = '';
end
end
% 計(jì)算平均碼長
codeLengths = cellfun(@length, codeTable(:, 2));
avgCodeLength = sum(codeLengths .* freq);
% 計(jì)算編碼效率
efficiency = 1 ./ avgCodeLength;
end
% 遞歸構(gòu)建編碼表
function codeTable = buildCodeTable(codeTable, cumProb, index, code)
if index > length(codeTable)
return;
end
if cumProb(index) <= 0.5
codeTable{index, 2} = [code, '0'+' '];
codeTable = buildCodeTable(codeTable, cumProb, index+1, [code, '0']);
else
codeTable{index, 2} = [code, '1'+' '];
codeTable = buildCodeTable(codeTable, cumProb, index+1, [code, '1']);
end
end
完結(jié) 撒花
到了這里,關(guān)于如和使用matlab實(shí)現(xiàn)香農(nóng)編碼和解碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!