開発環境 |
Microsoft Visual C++ 2010 Express (SP1) |
実行環境 |
Microsoft Windows XP Home Edition (SP3) |
プロジェクトの種類 |
Win32 コンソール アプリケーション |
プロジェクト名 |
huffman |
アプリケーションの種類 |
コンソール アプリケーション |
追加のオプション |
空のプロジェクト |
作成中。
参考
- ハフマン符号 - Wikipedia
huffman.cpp
#include <map>
// 型定義
typedef unsigned char UCHAR;
typedef struct {
int aiChild[2];
} TreeNode;
typedef struct {
int iCode;
int iSize;
} CodeInfo;
typedef struct {
int iCount;
int iIndex;
} DecIndex;
typedef struct {
int iCode;
int iValue;
} DecTable;
typedef std::multimap<int,int> mmii;
// 関数プロトタイプ宣言
void dfs(int iIndex, int iCode, int iSize);
int Encode(int iCode, int iSize);
int Decode(int iDataLen);
int FetchBit();
// グローバル変数
static TreeNode g_aTreeNode[511];
static CodeInfo g_aCodeInfo[256];
static DecIndex g_aDecIndex[16];
static DecTable g_aDecTable[256];
static UCHAR g_aucCode[1024];
static int g_iCodeIndex = 0;
static UCHAR g_aucDecBuf[1024];
static int g_iDecIndex;
int main()
{
UCHAR aucData[] = "government of the people, by the people, for the people";
int aiCount[256] = {0};
mmii mmQueue;
mmii::iterator it;
char acStr[32+1];
int iCount;
int i;
// 各バイト値の発生回数を数える
int iDataLen = strlen((char*)aucData);
for (i = 0; i < iDataLen; i++) {
aiCount[aucData[i]]++;
}
for (i = 0; i < 256; i++) {
if (aiCount[i] == 0) {
continue;
}
printf("'%c'=%d\n", i, aiCount[i]);
}
// ハフマン木を作成
for (i = 0; i < 256; i++) {
if (aiCount[i]) {
mmQueue.insert(mmii::value_type(aiCount[i], i));
}
}
int iIndex = 256;
while (1 < mmQueue.size()) {
int aiKey[2];
iCount = 0;
for (i = 0; i < 2; i++) {
it = mmQueue.begin();
aiKey[i] = (*it).first;
g_aTreeNode[iIndex].aiChild[i] = (*it).second;
mmQueue.erase(it);
iCount += aiKey[i];
}
mmQueue.insert(mmii::value_type(iCount, iIndex));
printf("0x%02X(%d) = 0x%02X(%d) + 0x%02X(%d)\n", iIndex, iCount,
g_aTreeNode[iIndex].aiChild[0], aiKey[0],
g_aTreeNode[iIndex].aiChild[1], aiKey[1]);
iIndex++;
}
it = mmQueue.begin();
int iRoot = (*it).second;
// 深さ優先探索でバイト値→符号情報を作成
dfs(iRoot, 0, 0);
for (i = 0; i < 256; i++) {
int iSize = g_aCodeInfo[i].iSize;
if (iSize == 0) {
continue;
}
_ltoa_s(0x80000000 | g_aCodeInfo[i].iCode, acStr, _countof(acStr), 2);
printf("'%c'=%d %s\n", i, iSize, acStr + 32 - iSize);
}
// 符号化
for (i = 0; i < iDataLen; i++) {
Encode(g_aCodeInfo[aucData[i]].iCode, g_aCodeInfo[aucData[i]].iSize);
}
Encode(0, 0);
for (i = 0; i < g_iCodeIndex; i++) {
_ltoa_s(0x100 | g_aucCode[i], acStr, _countof(acStr), 2);
printf("%s%c", acStr + 1, " - \n"[i % 8]);
}
if (i % 8) {
printf("\n");
}
// 復号テーブル作成
int iDecIndex = 0;
for (iIndex = 0; iIndex < 16; iIndex++) {
g_aDecIndex[iIndex].iIndex = iDecIndex;
iCount = 0;
for (i = 0; i < 256; i++) {
if (g_aCodeInfo[i].iSize != iIndex + 1) {
continue;
}
g_aDecTable[iDecIndex].iValue = i;
g_aDecTable[iDecIndex].iCode = g_aCodeInfo[i].iCode;
iDecIndex++;
iCount++;
}
g_aDecIndex[iIndex].iCount = iCount;
}
// 復号
Decode(iDataLen);
g_aucDecBuf[g_iDecIndex] = 0x00;
printf("%s\n", g_aucDecBuf);
return 0;
}
// 深さ優先探索でバイト値→符号情報を作成
void dfs(int iIndex, int iCode, int iSize)
{
if (iIndex < 256) {
g_aCodeInfo[iIndex].iCode = iCode;
g_aCodeInfo[iIndex].iSize = iSize;
} else {
dfs(g_aTreeNode[iIndex].aiChild[0], iCode << 1, iSize + 1);
dfs(g_aTreeNode[iIndex].aiChild[1], iCode << 1 | 1, iSize + 1);
}
}
// 符号化
int Encode(int iCode, int iSize)
{
static int s_iCode;
static int s_iSize = 0;
if (iSize == 0) {
if (s_iSize) {
s_iCode = s_iCode << (8 - s_iSize) | 0xFF >> s_iSize;
g_aucCode[g_iCodeIndex++] = s_iCode;
}
return 0;
}
s_iCode = s_iCode << iSize | iCode;
s_iSize += iSize;
while (8 <= s_iSize) {
s_iSize -= 8;
g_aucCode[g_iCodeIndex++] = s_iCode >> s_iSize;
}
return 0;
}
// 復号
int Decode(int iDataLen)
{
int iCode;
int iSize;
int iBit;
int iIndex;
int iValue;
int i;
for (g_iDecIndex = 0; g_iDecIndex < iDataLen; g_iDecIndex++) {
iCode = 0;
iSize = 0;
for (iValue = -1; iValue == -1; ) {
iBit = FetchBit();
iCode = iCode << 1 | iBit;
iSize++;
iIndex = g_aDecIndex[iSize - 1].iIndex;
for (i = 0; i < g_aDecIndex[iSize - 1].iCount; i++) {
if (g_aDecTable[iIndex + i].iCode == iCode) {
iValue = g_aDecTable[iIndex + i].iValue;
break;
}
}
}
g_aucDecBuf[g_iDecIndex] = iValue;
}
return 0;
}
int FetchBit()
{
static int iCodeIndex = 0;
static int iCodeBit = 7;
int i;
i = g_aucCode[iCodeIndex] >> iCodeBit & 0x01;
if (--iCodeBit < 0) {
iCodeIndex++;
iCodeBit = 7;
}
return i;
}
出力
' '=9
','=2
'b'=1
'e'=11
'f'=2
'g'=1
'h'=3
'l'=3
'm'=1
'n'=2
'o'=6
'p'=6
'r'=2
't'=4
'v'=1
'y'=1
0x100(2) = 0x62(1) + 0x67(1)
0x101(2) = 0x6D(1) + 0x76(1)
0x102(3) = 0x79(1) + 0x2C(2)
0x103(4) = 0x66(2) + 0x6E(2)
0x104(4) = 0x72(2) + 0x100(2)
0x105(5) = 0x101(2) + 0x68(3)
0x106(6) = 0x6C(3) + 0x102(3)
0x107(8) = 0x74(4) + 0x103(4)
0x108(9) = 0x104(4) + 0x105(5)
0x109(12) = 0x6F(6) + 0x70(6)
0x10A(14) = 0x106(6) + 0x107(8)
0x10B(18) = 0x20(9) + 0x108(9)
0x10C(23) = 0x65(11) + 0x109(12)
0x10D(32) = 0x10A(14) + 0x10B(18)
0x10E(55) = 0x10C(23) + 0x10D(32)
' '=3 110
','=5 10011
'b'=6 111010
'e'=2 00
'f'=5 10110
'g'=6 111011
'h'=5 11111
'l'=4 1000
'm'=6 111100
'n'=5 10111
'o'=3 010
'p'=3 011
'r'=5 11100
't'=4 1010
'v'=6 111101
'y'=5 10010
11101101 01111010 01110010 11111110-00010111 10101100 10101101 10101011
11100110 01100010 01110000 01001111-01110101 00101101 01011111 00110011
00010011 10000010 01111010 11001011-10011010 10111110 01100110 00100111
00000111
government of the people, by the people, for the people
最終更新:2012年09月01日 16:47