基於哈夫曼編碼完成的檔案壓縮及解壓

2022-09-02 05:03:07 字數 3614 閱讀 8776

這幾天在較為認真的研究基於哈夫曼編碼的檔案壓縮及解壓,費了點時間,在這分享一下:

這裡用鏈式結構,非順序表結構;

檔案壓縮:

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)

此為乙個檔案資訊的類結構,包含字元,字元對應出現的次數,以及這個字元對應的哈夫曼編碼(能看到這篇部落格的星弟,對哈夫曼編碼不會陌生,這裡不再強調)

除了統計字元出現的次數及哈夫曼編碼,還完成了幾個運算子的過載

要獲取哈夫曼編碼,就得建立哈夫曼樹,建立哈夫曼樹用最小堆取操作,以下是最小堆建立過程

// 小堆

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;

};

最小堆裡也完成了很多介面,包括push  pop等

然後就是幾個壓縮和解壓的函式介面

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 系列作...