當前位置:首頁 » 文件管理 » 解壓縮算啦

解壓縮算啦

發布時間: 2022-08-27 13:07:38

❶ 求助:用java實現哈夫曼編碼壓縮解壓演算法

你好,由於內容比較多,先概述一下先。如圖所示,為我寫的一個壓縮軟體,原理是利用哈弗曼演算法實現的。我將資料整理好稍後就發到你郵箱,但在這里簡要說明一下代碼。

請看我的空間

http://hi..com/%D2%B6%BF%C6%C1%BC/blog

中的文章共5篇(太長了)

http://hi..com/%D2%B6%BF%C6%C1%BC/blog/item/93c35517bb528146f2de32fd.html

1.HuffmanTextEncoder類完成壓縮功能,可直接運行,壓縮測試用文本文件。

2.HuffmanTextDecoder類完成解壓縮功能,可直接運行,解壓縮壓縮後的文本文件。

3.BitReader,工具類,實現對BufferedInputStream的按位讀取。

4.BitWriter,工具類,實現按位寫入的功能。該類來自網路。

5.MinHeap<T>,模板工具類,實現了一個最小堆。生成Huffman樹時使用。

❷ 解壓縮是什麼意思

解壓縮,計算機術語,就是將一個通過軟體壓縮的文檔、文件等各種東西恢復到壓縮之前的樣子,這種形式以利於傳輸或存儲。其原理就是利用壓縮軟體把二進制信息中相同的字元串以特殊字元標記來達到壓縮的目。

1、在360安全衛士里,找到軟體管家,下載360壓縮軟體。

(2)解壓縮算啦擴展閱讀:

1、手機網路瀏覽器不具有解壓縮功能,如果想要在手機上查看壓縮文件,可以下載手機版本的解壓縮軟體,比如RAR for Android、文件全能王等等。

2、最受歡迎的壓縮軟體RAR for Android,RAR是來自RARLAB的官方版本,支持創建RAR和ZIP,

3、解壓RAR, RAR5, ZIP, TAR, GZ, BZ2, XZ, 7z, ISO, ARJ,支持ZIP和RAR的修復,基準測試與WinRAR兼容,支持恢復記錄,恢復卷,固實壓縮,多核壓縮。

4、下載的壓縮軟體--文件全能王,對國人永久免費,千萬android機友首選文件全能王,強大的文件傳輸能力

5、通過瀏覽器即實現跨三平台文件傳輸(android、蘋果、電腦,通過WiFi或自建熱點零流量飛速妙傳各類文件。

❸ 怎樣破解壓縮文件的解壓碼

方法/步驟

11/11分步閱讀

下載快解密碼讀取工具

2/11

製作一個壓縮包,密碼隨便設置



查看剩餘1張圖

3/11

打開快解密碼讀取工具,切換到「壓縮包密碼」頁面



4/11

壓縮包格式選擇對應的格式,現在我破解的是「rar」格式的,所以選用「rar」,演算法默認選擇「AES」即可,不做處理即可,如果破解失敗,則是演算法不正確,由於不同壓縮軟體和壓縮格式使用的演算法不相同,我們依次換演算法破解即可,破解演算法肯定是3種演算法中的一種。



5/11

將點擊「打開文件」,打開需要破解密碼的壓縮包



查看剩餘2張圖

6/11

點擊「快速破解按鈕」,會看到軟體開始破解壓縮包文件



7/11

大約2-3分鍾後,提示密碼破解成功,並顯示出密碼



8/11

如果我們需要破解其他格式的壓縮包文件如ZIP,方法類似,按以上步驟操作即可,有時會遇到破解失敗的情況,換一種演算法即可,看下面例子:

9/11

打開軟體,「壓縮包格式」選擇「ZIP」,演算法使用「AES」,然後打開一個已經加密的壓縮包文件「測試3.zip」(測試了幾個軟體加密的壓縮包,只有這個不是AES演算法的)



查看剩餘2張圖

10/11

點擊「快速破解」,開始破解,等待,看到一個失敗的提示「破解失敗,請換一種方法重試!!!」



查看剩餘1張圖

11/11

這里,我們更換演算法,重新點擊「快速破解」,等待了2分鍾,看到了破解成功的提示。



查看剩餘2張圖

❹ 利用huffman樹實現文件的壓縮與解壓

這是本人寫的動態哈夫曼壓縮演算法實現,壓縮與解壓縮時,
根據文件內容自動生成哈夫曼樹,並動態調整節點的權重
和樹的形狀。900MHZ的PIII賽揚每秒鍾可以壓縮的好幾MB
的數據,只是壓縮率不高,文本文件的壓縮後容量一般可
以減少25%,比RAR差遠了。

源文件共三個,你在VC6.0中新建一個空的命令行項目,
將它們加進去,編譯完就可以用了。

===========hfm.cpp===================

#include <stdio.h>
#include <string.h>
#include <io.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "Huffman.h"

int wh;
int rh;

bool Write(unsigned char *s,int len){
_write(wh,s,len);
return true;
}

bool OpenFile(char* source,char* target){
int w_flag=_O_WRONLY | _O_CREAT | _O_EXCL | _O_BINARY;
int r_flag=_O_RDONLY | _O_BINARY;

rh=_open(source,r_flag,_S_IREAD | _S_IWRITE);
wh=_open(target,w_flag,_S_IREAD | _S_IWRITE);

if(rh==-1 || wh==-1){
if(rh!=-1){
_close(rh);
printf("\n打開文件:'%s'失敗!",target);
}
if(wh!=-1){
_close(wh);
printf("\n打開文件:'%s'失敗!",source);
}

return false;
}else{
return true;
}
}

void PrintUsage(){
printf("\n以動態哈夫曼演算法壓縮或解壓縮文件。\n\n");
printf("\thfm -?\t\t\t\t顯示幫助信息\n");
printf("\thfm -e -i source -o target\t壓縮文件\n");
printf("\thfm -d -i source -o target\t解壓縮文件\n\n");
}

void main(int argc,char *args[]){
int mode,i,j,K=0;
char src[4096];
char target[4096];
unsigned char buffer[BUFFER_SIZE];
Huffman *h;

mode=0;
for(i=1;i<argc;i++){
if(args[i][0]=='-' || args[i][0]=='/'){
switch(args[i][1]){
case '?':
mode=0;//幫助
break;
case 'e':
case 'E':
mode=1;//壓縮
break;
case 'd':
case 'D':
mode=2;//解壓縮
break;
case 'o':
case 'O':
if(i+1>=argc){
mode=0;
}else{//輸出文件
j=0;
while(args[i+1][j]!='\0' && j<4096){
target[j++]=args[i+1][j];
}
if(j==4096){
mode=0;
}else{
target[j]='\0';
K |= 1;
}
}
break;
case 'i':
case 'I':
if(i+1>=argc){
mode=0;
}else{//輸入文件
j=0;
while(args[i+1][j]!='\0' && j<4096){
src[j++]=args[i+1][j];
}
if(j==4096){
mode=0;
}else{
src[j]='\0';
K |=2;
}
}
break;
}
}
}

if(K!=3)mode=0;

switch(mode){
case 0:
PrintUsage();
return;
case 1://壓縮
if(!OpenFile(src,target))return;
h=new Huffman(&Write,true);
i=BUFFER_SIZE;
while(i==BUFFER_SIZE){
i=_read(rh,buffer,BUFFER_SIZE);
h->Encode(buffer,i);
}
delete h;
_close(rh);
_close(wh);
printf("壓縮完畢!");
break;
case 2://解壓縮
if(!OpenFile(src,target))return;
h=new Huffman(&Write,false);
i=BUFFER_SIZE;
while(i==BUFFER_SIZE){
i=_read(rh,buffer,BUFFER_SIZE);
h->Decode(buffer,i);
}
delete h;
_close(rh);
_close(wh);
printf("解壓縮完畢!");
break;
}

}

=======end of hfm.cpp=======================

=======Huffman.cpp=============================
// Huffman.cpp: implementation of the Huffman class.
//
//////////////////////////////////////////////////////////////////////

#include "Huffman.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Huffman::Huffman(Output *output,bool mode)
{
Hbtree *tmp;
int i;

this->mode=mode;

//設置輸出函數,當緩沖區滿時,將調用該函數輸出
this->output=output;

//初始化列表
for(i=0;i<LIST_LENGTH;i++)this->list[i]=NULL;

//初始化哈夫曼樹
this->root=this->NewNode(NOT_CHAR,LEFT,NULL);
this->current=this->root;
tmp=this->NewNode(CODE_ESCAPE,RIGHT,root);
tmp->count=1;
tmp=this->NewNode(CODE_FINISH,LEFT,root);
tmp->count=0;
root->count=root->child[LEFT]->count+root->child[RIGHT]->count;

//設置緩沖區指針
this->char_top=BOTTOM_BIT;
this->bit_top=TOP_BIT;
this->buffer[0]=0;

//重構哈夫曼樹的最大計數值
this->max_count=MAX_COUNT;
this->shrink_factor=SHRINK_FACTOR;
this->finished=false;
}

Huffman::~Huffman()
{
if(this->mode==true){//如果是編碼
//輸出結束碼
this->OutputEncode(CODE_FINISH);
this->char_top++;
}

//強制清空緩沖區
this->Flush();

//釋放空間
this->ReleaseNode(this->root);
}

Hbtree * Huffman::NewNode(int value, int index, Hbtree *parent)
{
Hbtree *tmp=new Hbtree;
tmp->parent=parent;
tmp->child[0]=NULL;
tmp->child[1]=NULL;
tmp->count=(1 << SHRINK_FACTOR);
tmp->index=(index==0) ? 0 : 1;
tmp->value=value;

if(value!=NOT_CHAR)this->list[tmp->value]=tmp;
if(parent!=NULL)parent->child[tmp->index]=tmp;
return tmp;
}

void Huffman::ReleaseNode(Hbtree *node)
{
if(node!=NULL){
this->ReleaseNode(node->child[LEFT]);
this->ReleaseNode(node->child[RIGHT]);
delete node;
}
}

//輸出一位編碼
int Huffman::OutputBit(int bit)
{
unsigned char candidates[]={1,2,4,8,16,32,64,128};

if(bit!=0)
this->buffer[this->char_top] |= candidates[this->bit_top];
this->bit_top--;
if(this->bit_top < BOTTOM_BIT){
this->bit_top=TOP_BIT;
this->char_top++;

if(this->char_top >= BUFFER_SIZE){//輸出緩沖區
this->output(this->buffer,BUFFER_SIZE);
this->char_top=0;
}

this->buffer[this->char_top]=0;
}
return 0;
}

//輸出緩沖區
int Huffman::Flush()
{
this->output(this->buffer,this->char_top);
this->char_top=0;
return 0;
}

int Huffman::Encode(unsigned char c)
{
int value=c,
candidates[]={128,64,32,16,8,4,2,1},
i;

if(this->list[value]==NULL){//字元不存在於哈夫曼樹中
//輸出轉義碼
this->OutputEncode(CODE_ESCAPE);
//輸出字元
for(i=0;i<8;i++)this->OutputBit(value & candidates[i]);

this->InsertNewNode(value);

}else{
//輸出字元編碼
this->OutputEncode(value);

//重新調整哈夫曼樹
this->BalanceNode(this->list[value]->parent);
}

//重組哈夫曼樹
if(this->root->count>=this->max_count)
this->RearrangeTree();

return 0;
}

void Huffman::BalanceNode(Hbtree *node)
{
Hbtree *parent,*child,*brother;
int i,j;

parent=node->parent;
if(parent==NULL)return;//根節點無需調整

if(node->value==NOT_CHAR){//非葉子節點
child=node->child[LEFT]->count > node->child[RIGHT]->count ?
node->child[LEFT] : node->child[RIGHT];

if(child->count > parent->count - node->count){
//失衡

i=!(node->index);
j=child->index;
node->count=parent->count - child->count;
brother=parent->child[i];

node->child[j]=brother;
brother->index=j;
brother->parent=node;

parent->child[i]=child;
child->index=i;
child->parent=parent;
}
}
this->BalanceNode(parent);
}

//輸出一個字元的編碼
int Huffman::OutputEncode(int value)
{
int stack[CODE_FINISH+2],top=0;
Hbtree *tmp=this->list[value];

//輸出編碼
if(value<=MAX_VALUE){//字元
while(tmp!=NULL){
stack[top++]=tmp->index;
tmp->count++;
tmp=tmp->parent;
}
}else{//控制碼
while(tmp!=NULL){
stack[top++]=tmp->index;
tmp=tmp->parent;
}
}
top--;
while(top>0){
this->OutputBit(stack[--top]);
}

return 0;
}

void Huffman::PrintNode(Hbtree *node,int level)
{
int i;
if(node){
for(i=0;i<level*3;i++)printf(" ");
printf("%p P:%p L:%p R:%p C:%d",node,node->parent,node->child[0],node->child[1],node->count);
if(node->value!=NOT_CHAR)printf(" V:%d",node->value);
printf("\n");

this->PrintNode(node->child[LEFT],level+1);
this->PrintNode(node->child[RIGHT],level+1);
}
}

int Huffman::Encode(unsigned char *s, int len)
{
int i;
for(i=0;i<len;i++)this->Encode(s[i]);
return 0;
}

void Huffman::PrintTree()
{
this->PrintNode(this->root,0);
}

int Huffman::RecountNode(Hbtree *node)
{
if(node->value!=NOT_CHAR)return node->count;
node->count=
this->RecountNode(node->child[LEFT]) +
this->RecountNode(node->child[RIGHT]);
return node->count;
}

void Huffman::RearrangeTree()
{
int i,j,k;
Hbtree *tmp,*tmp2;

//所有非控制碼的計數值右移shrink_factor位,並刪除計數值為零的節點
for(k=0;k<=MAX_VALUE;k++){
if(this->list[k]!=NULL){
tmp=this->list[k];
tmp->count >>= this->shrink_factor;
if(tmp->count ==0){
this->list[k]=NULL;
tmp2=tmp->parent;
i=tmp2->index;
j=!(tmp->index);
if(tmp2->parent!=NULL){
tmp2->parent->child[i]=tmp2->child[j];
tmp2->child[j]->parent=tmp2->parent;
tmp2->child[j]->index=i;
}else{
this->root=tmp2->child[j];
this->current=this->root;
this->root->parent=NULL;
}
delete tmp;
delete tmp2;
}
}
}

//重新計數
this->RecountNode(this->root);

//重新調整平衡
for(i=0;i<=MAX_VALUE;i++){
if(this->list[i]!=NULL)
this->BalanceNode(this->list[i]->parent);
}
}

void Huffman::InsertNewNode(int value)
{
int i;
Hbtree *tmp,*tmp2;

//將字元加入哈夫曼樹
tmp2=this->list[CODE_FINISH];
tmp=this->NewNode(NOT_CHAR, tmp2->index, tmp2->parent);
tmp->child[LEFT]=tmp2;
tmp2->index=LEFT;
tmp2->parent=tmp;

tmp2=this->NewNode(value,RIGHT,tmp);
tmp->count=tmp->child[LEFT]->count+tmp->child[RIGHT]->count;
i=tmp2->count;
while((tmp=tmp->parent)!=NULL)tmp->count+=i;
//從底向上調整哈夫曼樹
this->BalanceNode(tmp2->parent);
}

int Huffman::Decode(unsigned char c)
{
this->Decode(c,7);
return 0;
}

int Huffman::Decode(unsigned char *s,int len)
{
int i;
for(i=0;i<len;i++)this->Decode(s[i]);
return 0;
}

int Huffman::Decode(unsigned char c, int start)
{
int value=c,
candidates[]={1,2,4,8,16,32,64,128},
i,j;
Hbtree *tmp;

if(this->finished)return 0;

i=start;
if(this->current==NULL){//轉義狀態下
while(this->remain >= 0 && i>=0){
if((candidates[i] & value) !=0){
this->literal |= candidates[this->remain];
}
this->remain--;
i--;
}

if(this->remain < 0){//字元輸出完畢

//輸出字元
this->OutputChar(this->literal);
//將字元插入哈夫曼樹
this->InsertNewNode(literal);
//重組哈夫曼樹
if(this->root->count>=this->max_count)
this->RearrangeTree();

//設置環境
this->current=this->root;
}
}else{
j=((value & candidates[i])!=0)?1:0;
tmp=this->current->child[j];
i--;
while(tmp->value==NOT_CHAR && i>=0){
j=((value & candidates[i])!=0)?1:0;
tmp=tmp->child[j];
i--;
}

if(tmp->value==NOT_CHAR){//中間節點
this->current=tmp;
}else{
if(tmp->value<=MAX_VALUE){//編碼內容
j=tmp->value;
this->OutputChar((unsigned char)j);

//修改計數器
tmp=this->list[j];
while(tmp!=NULL){
tmp->count++;
tmp=tmp->parent;
}
//調整平衡度
this->BalanceNode(this->list[j]->parent);

//重組哈夫曼樹
if(this->root->count>=this->max_count)
this->RearrangeTree();

//設置環境
this->current=this->root;
}else{
if(tmp->value==CODE_ESCAPE){//轉義碼
this->current=NULL;
this->remain=7;
this->literal=0;
}else{//結束碼
this->finished=true;
return 0;
}
}
}

}

if(i>=0)this->Decode(c,i);
return 0;
}

int Huffman::OutputChar(unsigned char c)
{
this->buffer[this->char_top++]=c;
if(this->char_top>=BUFFER_SIZE){//輸出緩沖區
this->output(this->buffer,BUFFER_SIZE);
this->char_top=0;
}
return 0;
}

========end of Huffman.cpp==================

========Huffman.h============================
// Huffman.h: interface for the Huffman class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(NULL)
#include <stdio.h>
#endif

#if !defined(AFX_HUFFMAN_H__B1F1A5A6_FB57_49B2_BB67_6D1764CC04AB__INCLUDED_)
#define AFX_HUFFMAN_H__B1F1A5A6_FB57_49B2_BB67_6D1764CC04AB__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define MAX_COUNT 65536 //最大計數值,大於此值時
#define MAX_VALUE 255 //編碼的最大值
#define CODE_ESCAPE MAX_VALUE+1 //轉義碼
#define CODE_FINISH MAX_VALUE+2 //結束碼
#define LIST_LENGTH MAX_VALUE+3 //編碼列表長度
#define SHRINK_FACTOR 2 //減小的比例,通過右移位實現
#define LEFT 0 //左孩子索引
#define RIGHT 1 //右孩子索引
#define NOT_CHAR -1 //非字元

#define TOP_BIT 7 //字元最高位
#define BOTTOM_BIT 0 //字元最低位
#define BUFFER_SIZE 81920 //緩沖區大小

//輸出函數
typedef bool (Output)(unsigned char *s,int len);

//哈夫曼樹的節點定義
typedef struct Hnode{
int count;//計數器
int index;//父節點的孩子索引(0--左孩子,1--右孩子)
Hnode* child[2];
Hnode* parent;
int value;
}Hbtree;

class Huffman
{
private:
//輸出一個解碼的字元
int OutputChar(unsigned char c);
//從指定位置開始解碼
int Decode(unsigned char c,int start);
//插入一個新節點
void InsertNewNode(int value);
//重新調整哈夫曼樹構型
void RearrangeTree();
//對各節點重新計數
int RecountNode(Hbtree *node);
//列印哈夫曼樹節點
void PrintNode(Hbtree *node,int level);
//輸出一個值的編碼
int OutputEncode(int value);
//調節哈夫曼樹節點使之平衡
void BalanceNode(Hbtree *node);
//輸出一位編碼
int OutputBit(int bit);
//釋放哈夫曼樹節點
void ReleaseNode(Hbtree *node);
//新建一個節點
Hbtree *NewNode(int value,int index, Hbtree *parent);
//輸出函數地址
Output *output;
//哈夫曼樹根地址
Hbtree *root;
//哈夫曼編碼單元列表
Hbtree *list[LIST_LENGTH];
//輸出緩沖區
unsigned char buffer[BUFFER_SIZE];
//緩沖區頂
int char_top,bit_top;
//收縮哈夫曼樹參數
int max_count,shrink_factor;
//工作模式,true--編碼,false--解碼
bool mode;
//解碼的當前節點
Hbtree *current;
int remain;//當前字元剩餘的位數
unsigned char literal;//按位輸出的字元
bool finished;

public:

//解碼指定長度的字元串
int Decode(unsigned char *s,int len);
//解碼一個字元
int Decode(unsigned char c);
//列印哈夫曼樹
void PrintTree();
//編碼指定長度的字元串
int Encode(unsigned char *s,int len);
//編碼一個字元
int Encode(unsigned char c);
//清空緩沖區
int Flush();

//output指輸出函數,mode指工作模式,true--編碼,false--解碼
Huffman(Output *output,bool mode);

//析構函數
virtual ~Huffman();
};

#endif // !defined(AFX_HUFFMAN_H__B1F1A5A6_FB57_49B2_BB67_6D1764CC04AB__INCLUDED_)

================end of Huffman.h==================

祝你好運!

❺ 解壓的最好方法是什麼

解壓的方法,你可以試一試下面的方法之一:1、接受現實的自己 。給自己增加許多額外要求和太大壓力的人,常是追求完美的人,他們對自身極為 苛刻,總是不能很好地悅納自己。那麼,從現在開始,轉向自我接受。對自己並不完美的外貌、有些瑕 疵的為人處世,以及並非盡善盡美的工作狀態,都要努力贊賞。有時應當心安理得地承認自己的本來面目,這樣一定會讓你感覺輕松很多。
2、結交快樂的朋友。 中國有句古語:「近朱者赤,近墨者黑。」如果你總是接觸沉悶憂郁的人,久之你也會感到自己變得很壓抑、很沉悶;如果你總是結交快樂、輕松的朋友,你就會在不知不覺中漸漸地變成一個快樂而熱力四射的人。人的神情和態度就像麻疹一樣,是有感染力的。那麼,讓快樂、輕松的朋友把快樂感染給你,在面對壓力的時候,你就會感到不那麼沉重。
3、傾訴和釋放。 如果你願意,可以向你信賴的朋友傾訴你的煩惱,告訴他所承擔的一切和你的心情。如果你更願意自己一個人來面對,那麼就找一個寂靜優美的地方,在落葉的最深處任憑情緒自由釋放。哭泣,大聲地呼喊,或者跑一跑、跳一跳,別想自己是不是夠文雅,盡情地釋放心頭那種喘不過氣的感覺。讓自己在接下來的一輪挑戰中輕裝上陣。
4、親近大自然。 人類本來就是自然的兒女。當你感到壓力太重時,不妨暫時放下手頭的工作,利用閑暇散散步,打打球,短程的旅遊對於緩沖壓力更不失為一個「磨刀不誤砍柴工」的有效方法。在綠樹青山之間,在江河大海邊,讓一切壓力都隨風而去。如果實在抽不開身,在辦公室里也可以「忙裡偷閑」地讓心靈回歸自然。如每天工作三小時,放下工作,向窗外眺望三五分鍾,視野盡量向開闊的遠處伸展,在大腦和視覺疲勞減輕的同時,壓力也會得到釋放。
5、來一點情趣。 給自己一個空間,給自己一點時間,做一個「有趣」的人,用一種其他的活動或愛好(如讀書、聽音樂、烹飪、唱歌等等)來調動內心輕松、快樂的情緒,讓正性情緒和負性情緒相互抵消,能夠有效地減輕心理壓力。
6、膳食平衡。 咖啡、濃茶並無益處,應遵循健康、平衡的飲食結構,保持身體的最佳健康狀態,這是承擔巨大壓力挑戰的生理基礎。有的人為了方便省事,常用快餐食品來應付日常飲食,結果會導致高熱量高脂肪食品攝入過多,蔬菜水果攝入太少。熱量攝入多會造成代謝物質在體內堆積,加重了身體器官的負擔,會感到身體容易疲勞,耐負荷力也相應地變差。而且,有一些高負荷的人養成了靠濃咖啡和濃茶提神的習慣,以此緩解緊張情緒,應付睡眠的不足。事實上,疲勞是承擔過度壓力後的正常生理反應,最佳消除方式是睡眠,咖啡和濃茶只能起到暫時興奮的作用,且會加速體能的消耗,對真正緩解疲勞和減輕壓力並無益處。壓力大的人可經常吃一些燕麥片等富含纖維的食品。

❻ 霍夫曼 解壓縮

哈夫曼編碼(Huffman Coding)是一種編碼方式,以哈夫曼樹—即最優二叉樹,帶權路徑長度最小的二叉樹,經常應用於數據壓縮。 在計算機信息處理中,「哈夫曼編碼」是一種一致性編碼法(又稱"熵編碼法"),用於數據的無損耗壓縮。這一術語是指使用一張特殊的編碼表將源字元(例如某文件中的一個符號)進行編碼。這張編碼表的特殊之處在於,它是根據每一個源字元出現的估算概率而建立起來的(出現概率高的字元使用較短的編碼,反之出現概率低的則使用較長的編碼,這便使編碼之後的字元串的平均期望長度降低,從而達到無損壓縮數據的目的)。這種方法是由David.A.Huffman發展起來的。 例如,在英文中,e的出現概率很高,而z的出現概率則最低。當利用哈夫曼編碼對一篇英文進行壓縮時,e極有可能用一個位(bit)來表示,而z則可能花去25個位(不是26)。用普通的表示方法時,每個英文字母均佔用一個位元組(byte),即8個位。二者相比,e使用了一般編碼的1/8的長度,z則使用了3倍多。倘若我們能實現對於英文中各個字母出現概率的較准確的估算,就可以大幅度提高無損壓縮的比例。

本文描述在網上能夠找到的最簡單,最快速的哈夫曼編碼。本方法不使用任何擴展動態庫,比如STL或者組件。只使用簡單的C函數,比如:memset,memmove,qsort,malloc,realloc和memcpy。
因此,大家都會發現,理解甚至修改這個編碼都是很容易的。

背景
哈夫曼壓縮是個無損的壓縮演算法,一般用來壓縮文本和程序文件。哈夫曼壓縮屬於可變代碼長度演算法一族。意思是個體符號(例如,文本文件中的字元)用一個特定長度的位序列替代。因此,在文件中出現頻率高的符號,使用短的位序列,而那些很少出現的符號,則用較長的位序列。
編碼使用
我用簡單的C函數寫這個編碼是為了讓它在任何地方使用都會比較方便。你可以將他們放到類中,或者直接使用這個函數。並且我使用了簡單的格式,僅僅輸入輸出緩沖區,而不象其它文章中那樣,輸入輸出文件。
bool CompressHuffman(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen);
bool DecompressHuffman(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen);
要點說明
速度
為了讓它(huffman.cpp)快速運行,我花了很長時間。同時,我沒有使用任何動態庫,比如STL或者MFC。它壓縮1M數據少於100ms(P3處理器,主頻1G)。
壓縮
壓縮代碼非常簡單,首先用ASCII值初始化511個哈夫曼節點:
CHuffmanNode nodes[511];
for(int nCount = 0; nCount < 256; nCount++)
nodes[nCount].byAscii = nCount;
然後,計算在輸入緩沖區數據中,每個ASCII碼出現的頻率:
for(nCount = 0; nCount < nSrcLen; nCount++)
nodes[pSrc[nCount]].nFrequency++;
然後,根據頻率進行排序:
qsort(nodes, 256, sizeof(CHuffmanNode), frequencyCompare);
現在,構造哈夫曼樹,獲取每個ASCII碼對應的位序列:
int nNodeCount = GetHuffmanTree(nodes);
構造哈夫曼樹非常簡單,將所有的節點放到一個隊列中,用一個節點替換兩個頻率最低的節點,新節點的頻率就是這兩個節點的頻率之和。這樣,新節點就是兩個被替換節點的父節點了。如此循環,直到隊列中只剩一個節點(樹根)。
// parent node
pNode = &nodes[nParentNode++];
// pop first child
pNode->pLeft = PopNode(pNodes, nBackNode--, false);
// pop second child
pNode->pRight = PopNode(pNodes, nBackNode--, true);
// adjust parent of the two poped nodes
pNode->pLeft->pParent = pNode->pRight->pParent = pNode;
// adjust parent frequency
pNode->nFrequency = pNode->pLeft->nFrequency + pNode->pRight->nFrequency;
這里我用了一個好的訣竅來避免使用任何隊列組件。我先前就直到ASCII碼只有256個,但我分配了511個(CHuffmanNode nodes[511]),前255個記錄ASCII碼,而用後255個記錄哈夫曼樹中的父節點。並且在構造樹的時候只使用一個指針數組(ChuffmanNode *pNodes[256])來指向這些節點。同樣使用兩個變數來操作隊列索引(int nParentNode = nNodeCount;nBackNode = nNodeCount –1)。
接著,壓縮的最後一步是將每個ASCII編碼寫入輸出緩沖區中:
int nDesIndex = 0;
// loop to write codes
for(nCount = 0; nCount < nSrcLen; nCount++)
{
*(DWORD*)(pDesPtr+(nDesIndex>>3)) |=
nodes[pSrc[nCount]].dwCode << (nDesIndex&7);
nDesIndex += nodes[pSrc[nCount]].nCodeLength;
}
(nDesIndex>>3): >>3 以8位為界限右移後到達右邊位元組的前面
(nDesIndex&7): &7 得到最高位.
注意:在壓縮緩沖區中,我們必須保存哈夫曼樹的節點以及位序列,這樣我們才能在解壓縮時重新構造哈夫曼樹(只需保存ASCII值和對應的位序列)。
解壓縮
解壓縮比構造哈夫曼樹要簡單的多,將輸入緩沖區中的每個編碼用對應的ASCII碼逐個替換就可以了。只要記住,這里的輸入緩沖區是一個包含每個ASCII值的編碼的位流。因此,為了用ASCII值替換編碼,我們必須用位流搜索哈夫曼樹,直到發現一個葉節點,然後將它的ASCII值添加到輸出緩沖區中:
int nDesIndex = 0;
DWORD nCode;
while(nDesIndex < nDesLen)
{
nCode = (*(DWORD*)(pSrc+(nSrcIndex>>3)))>>(nSrcIndex&7);
pNode = pRoot;
while(pNode->pLeft)
{
pNode = (nCode&1) ? pNode->pRight : pNode->pLeft;
nCode >>= 1;
nSrcIndex++;
}
pDes[nDesIndex++] = pNode->byAscii;
}

❼ RAR和ZIP兩種格式的壓縮演算法分別是什麼

RAR文件的擴展名是.rar(不區分大小寫,),MIME類型是application/x-rar-compressed。同樣是無損數據壓縮,RAR文件通常比ZIP文件壓縮比要高,但是壓縮速度較慢。因為RAR文件頭也要佔據一定空間,在數據壓縮餘地不大時,壓縮過的文件可能比原文件要大。RAR的一個主要優點是可以把文件壓縮目標分割到多個文件,並且很容易從這樣的分割的壓縮文件解壓出源文件。另外,RAR也支持緊縮格式,把所有文件壓縮到同一個數據區以加大壓縮比,代價是解壓一個單獨的文件時必須解壓其前面的所有文件。新的RAR的加密演算法使用的是AES,而舊的RAR的加密演算法是私有的。這兩種演算法都很難破解,所以在沒有密碼的情況下只能用字典暴力破解法來破解。RAR中也可以加入冗餘的修復信息,在文件損壞但是修復信息足夠完好時可以對壓縮包進行修復。

❽ 壓縮采樣的演算法是怎麼描述的

ADPCM(Adaptive
Differential
Pulse
Code
Molation),是一種針對
16bits(
或8bits或者更高)
聲音波形數據的一種有損壓縮演算法,它將聲音流中每次采樣的
16bit
數據以
4bit
存儲,所以壓縮比
1:4.
而且壓縮/解壓縮演算法非常簡單,所以是一種低空間消耗,高質量高效率聲音獲得的好途徑。保存聲音的數據文件後綴名為
.AUD
的大多用ADPCM
壓縮。

ADPCM
主要是針對連續的波形數據的,保存的是波形的變化情況,以達到描述整個波形的目的,由於它的編碼和解碼的過程卻很簡潔,列在後面,相信大家能夠看懂。

8bits采樣的聲音人耳是可以勉強接受的,而
16bit
采樣的聲音可以算是高音質了。ADPCM
演算法卻可以將每次采樣得到的
16bit
數據壓縮到
4bit
。需要注意的是,如果要壓縮/解壓縮得是立體聲信號,采樣時,聲音信號是放在一起的,需要將兩個聲道分別處理。
PCM是脈沖編碼調制的意思。AD是自適應增量的意思。
嚴格說來,ADPCM不是壓縮方法。他的主要思想是,用差值替代絕對值。舉個例子,全班同學平均身高175CM:其中,我的身高170CM,這就是PCM方法;我的身高和平均值相比為-5cm,這就是DPCM,我的身高跟前一位同學相比為-10CM,前一位同學有多高我不知道他多高,你問他,這是ADPCM。比方不是太准確,大概就是這個意思。
在大多數情況下,數據值與平均值相差不大,所以用差值替代絕對值可以節省空間。
很高興回答樓主的問題
如有錯誤請見諒

❾ 常見的壓縮技術有哪兩種它們的主要特點是什麼

數據壓縮可分成兩種類型,一種叫做無損壓縮,另一種叫做有損壓縮。
無損壓縮是指使用壓縮後的數據進行重構(或者叫做還原,解壓縮),重構後的數據與原來的數據完全相同;無損壓縮用於要求重構的信號與原始信號完全一致的場合。一個很常見的例子是磁碟文件的壓縮。根據目前的技術水平,無損壓縮演算法一般可以把普通文件的數據壓縮到原來的1/2~1/4。一些常用的無損壓縮演算法有霍夫曼(Huffman)演算法和LZW(Lenpel-Ziv & Welch)壓縮演算法。
有損壓縮是指使用壓縮後的數據進行重構,重構後的數據與原來的數據有所不同,但不影響人對原始資料表達的信息造成誤解。有損壓縮適用於重構信號不一定非要和原始信號完全相同的場合。例如,圖像和聲音的壓縮就可以採用有損壓縮,因為其中包含的數據往往多於我們的視覺系統和聽覺系統所能接收的信息,丟掉一些數據而不至於對聲音或者圖像所表達的意思產生誤解,但可大大提高壓縮比。

熱點內容
洗腦緩存 發布:2024-10-13 11:59:53 瀏覽:921
安卓導航怎麼關閉自動升級 發布:2024-10-13 11:51:53 瀏覽:665
電腦配置120加1t什麼意思 發布:2024-10-13 11:51:10 瀏覽:412
方舟如何創建建造伺服器 發布:2024-10-13 11:21:05 瀏覽:598
win7用戶文件夾改名 發布:2024-10-13 11:16:53 瀏覽:703
小區門密碼如何重置 發布:2024-10-13 11:16:08 瀏覽:884
投訴上傳評證 發布:2024-10-13 11:03:55 瀏覽:427
pn結演算法 發布:2024-10-13 10:58:12 瀏覽:264
網路課程腳本 發布:2024-10-13 10:24:56 瀏覽:505
網上買電腦如何查看配置 發布:2024-10-13 10:17:29 瀏覽:798