這幾天在較為認真的研究基於哈夫曼編碼的檔案壓縮及解壓,費了點時間,在這分享一下:
這裡用鏈式結構,非順序表結構;
檔案壓縮:
1.獲取檔案資訊(這裡採用txt格式文字);
2.壓縮檔案;
3.寫配置檔案(便於解壓時用,無非就是存放原檔案的索引之類的,比如說,檔案中某個字元出現的個數,記錄下來)
4.解壓縮,使用壓縮後的檔案和配置檔案解壓檔案;
5.用比對軟體,比對解壓後的檔案和原始檔是否相同;
下面慢慢解析:
先看乙個檔案資訊類:
typedef long long longtype;此為乙個檔案資訊的類結構,包含字元,字元對應出現的次數,以及這個字元對應的哈夫曼編碼(能看到這篇部落格的星弟,對哈夫曼編碼不會陌生,這裡不再強調)struct fileinfo
fileinfo operator+(const fileinfo& x)
bool operator !=(const fileinfo& x) const };
bool operator<(const fileinfo info1,const fileinfo info2)
除了統計字元出現的次數及哈夫曼編碼,還完成了幾個運算子的過載
要獲取哈夫曼編碼,就得建立哈夫曼樹,建立哈夫曼樹用最小堆取操作,以下是最小堆建立過程
// 小堆最小堆裡也完成了很多介面,包括push pop等templatestruct less
};templatestruct greater
};template>
class heap
heap(const t* a, size_t size)
// 建堆
for(int i = (_arrays.size()-2)/2; i >= 0; --i)
}void push(const t& x)
void pop()
t& top()
bool empty()
int size()
void adjustdown(int root)
if(*_arrays[child] < _arrays[root])
//if(com(_arrays[child],_arrays[root]))
else
}} void adjustup(int child)
else
}}public:
vector_arrays;
};
然後就是幾個壓縮和解壓的函式介面
1.根據哈夫曼樹獲取哈夫曼變慢:
void _generatehuffmancode(huffmantreenode* root)_generatehuffmancode(root->_left);
_generatehuffmancode(root->_right);
//當前節點為葉子節點為空 才生成哈夫曼編碼
if (root->_left == nullptr && root->_right == nullptr)
else if (parent->_right == cur)
cur = parent;
parent = cur->_parent;
}reverse(code.begin(), code.end());
} }
2.根據最小堆建立哈夫曼樹;
void createtree(t *a, size_t size, const t& invalid)}while (s1.size() > 1)
_root = s1.top();
s1.pop();
}
bool _readline(file *foutlogfile, string& line)while (ch != '\n')
return true;
} }
4.檔案壓縮
//檔案壓縮bool compress(const char* filename)
huffmantreeht;
fileinfo invalid;
ht.createtree(_infos, 256, invalid);
//哈夫曼編碼
_generatehuffmancode(ht.getroot());
string compressfile = filename;
compressfile += ".huf";
//壓縮後的檔名 字尾為《輸入檔名+.huf》
file *fincompress = fopen(compressfile.c_str(), "wb"); //獲取string中的c字串
assert(fincompress);
fseek(fout, 0, seek_set);//將檔案指標移到開頭
char cha = fgetc(fout);
unsigned char inch = 0;
int index = 0; //乙個位元組的八位
while (!feof(fout))
if (++index == 8)
}cha = fgetc(fout);
} fclose(fout);
//如果index = 0 說明 上邊8位剛好存滿 不等 下乙個自己又出來了
if (index != 0) //處理最後乙個字元不夠的問題
fclose(fincompress);
}
5.寫配置檔案:
string logfile = filename;logfile += ".log";
file *log = fopen(logfile.c_str(), "wb");
assert(log);
string chinfo;
char str[128] = ; //沒空間 不可以
for (size_t i = 1; i < 256; ++i)
}fclose(log);
6.最後的檔案解壓:
//重構檔案
void _restorefiles(huffmantreenode*root, const char* fileneme,long long size)
else if (ch == 1)
if (pos == 0)
}fputc(cur->_weight._ch, over);
poss--;
} fclose(out);
fclose(over); }
void uncompress(const char* fileneme)//解壓縮
huffmantreef;
fileinfo invalid;
f.createtree(_infos, 256, invalid);
//根據重建的哈夫曼樹 還原檔案;
long long size = f.getroot()->_weight._count;
_restorefiles(f.getroot(), fileneme,size);
基於哈夫曼編碼的檔案壓縮
本篇主要介紹如何利用哈夫曼編碼使檔案進行壓縮 如何構建哈夫曼樹 歡迎提出問題和建議 blbagony 163.com 鏈結 哈夫曼樹template struct huffmannode 構建樹 huffman tree 是構造出來的物件,size返回樹中結點個數 每取乙個 top 就 pop 一次...
哈夫曼樹和哈夫曼編碼(檔案壓縮)
哈夫曼樹 huffman tree 帶權路徑長度 wpl 設二叉樹有n個葉子結點,每個葉子結點帶有權值wk,從根節點到每個葉子結點的長度為lk,則每個葉子結點帶權路徑長度之和就是 wk lk 求和 最優二叉樹或哈夫曼樹 wpl最小的二叉樹 哈夫曼樹的構造 每次把權值最小的兩棵二叉樹合併 1 huff...
基於Huffman哈夫曼編碼的檔案壓縮與解壓縮
一 實驗題目 用哈夫曼編碼實現檔案壓縮 二 實驗目的 了解檔案的概念 掌握線性鍊錶的插入 刪除等演算法 掌握huffman樹的概念及構造方法 掌握二叉樹的儲存結構及遍歷演算法 利用huffman樹及huffman編碼,掌握實現檔案壓縮的一般原理 三 實驗裝置與環境 微型計算機 windows 系列作...