热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

文件压缩解压的哈夫曼树实现

本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。

数据结构课程设计时写的

#include
//使用时间时调用
/
#ifndef T_MS //
#define T_MS //
DWORD start,stop; //
#endif //
/

// 常量定义
/
#ifndef G_C //
#define G_C //
#define N 1000 //
#define MAX 99999 //
#endif //
/
// 统计文件中各个字符时相关结构体
///
#ifndef W_C //
#define W_C //
struct Word_Count{ //
char word ; //字符类型 //
int count ; //字符出现次数 //
}; //
struct Word_Count_Array{ //
struct Word_Count wC[N]; //
int point; //定位指针(指向数组wC中第一个空位) //
}; //
#endif //
///
// 构建Huffuman树相关结构体
/
#ifndef H_T //
#define H_T //
struct Node{ //构建哈夫曼树的节点 //
char word; //
int count; //
struct Node *leftChild,*rightChild; //
int myAdrr,lfAdrr,rgAdrr; //自己|左孩子|右孩子 Adrress //
}; //便于文件中树的生成 //
struct Node_Array{ //
struct Node node[N]; //
int point; //
}; //
struct Dynamic_Array{ //动态数组 //
int dArray[N]; //
int point; //指向数组中第一个空位 //
}; //
struct WordCode{ //存储字符以及其编 //
char word; //字符 //
int code[N]; //Huffu编码 //
int point; //指向数组中第一个空位 //
}; //
struct WordCode_Array{ //存储字符以及其编码 //
struct WordCode wCode[N]; //
int point; //指向数组中wCode第一个空位 //
}; //
struct Dynamic_Array dyArr; //辅组存储编码的动态数组 //
struct WordCode_Array wCArr; //存储字符及其编码 //
int Pos=0; //
#endif //
/

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Function Module : Statistical character frequency *
* *
* Explain : 统计字符频率(Hz),需要缓冲数组buff. *
* *
* @author: luewang *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include"GlobalVCS.h"
/**
*
* Role: compare word to count
*
* Explain: 将传入的字符与存储字符的结构体数组
* 中的字符进行比较,更新字符出现次数
* (Hz)
*
* @return: 无
*
*/
void OperateWC(struct Word_Count_Array* wCA,char word){
int i = 0;
for(; i point ; i++){
if(word==wCA->wC[i].word){
wCA->wC[i].count+=1;
break;
}
}
if(i==wCA->point){
wCA->wC[i].word=word;
wCA->wC[i].count=1;
wCA->point=i+1;
}
}
/**
*
* Role: count word
*
* Explain: 统计各个字符出现的频率(Hz)
*
* @return: 字符频率结构体数组wCA
*
*/
struct Word_Count_Array SingleChar_Hz(char buff[],int n){
struct Word_Count_Array wCA; //存储各个字符出现频数的结构体数组 *
wCA.point=0;
for(int i = 0 ; i OperateWC(&wCA,buff[i]);
}

//控制台打印统计好的字符出现的频率
printf("+----------+-----------+\n");
printf("+ wCA:字符频率统计数组 +\n");
printf("+----------+-----------+\n");
printf("| word | count |\n");
printf("+----------+-----------+\n");
for(int i = 0 ; i printf("|%10c|%11d|\n",wCA.wC[i].word,wCA.wC[i].count);
printf("+----------+-----------+\n");
}

printf("...Over.....OK...\n\n");
return wCA;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Function Module (core code) : Establishment Of Huffuman Tree. *
* *
* Explain : *
* 使用从文件中统计的字符频率的结构体数组,循环先序遍历构建Huffu- *
* -man树,并另外使用结构体数组统计各个字符哈夫曼编码。 *
* *
* @author: luewang *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include"GlobalVCS.h"
#include"GlobalVCS.h"
/**
*
* Role: Sort of Insert
*
* Explain: 利用插入排序将统计好个字符频率的结构体数组wCA
* 进行升序排序.
*
* @return: 返回后续构建树所需要的节点的数组
*
*/
struct Node_Array InsertSort(struct Word_Count_Array *wCA){
int i,j;
int tmpCount;
char tmpChar;
for(i = 1 ; i point ; i++){
tmpCount = wCA->wC[i].count;
tmpChar = wCA->wC[i].word ;
for(j = i ; j > 0 && wCA->wC[j-1].count > tmpCount ; j--){
wCA->wC[j].count = wCA->wC[j-1].count;
wCA->wC[j].word = wCA->wC[j-1].word ;
}
wCA->wC[j].count = tmpCount;
wCA->wC[j].word = tmpChar ;
}
struct Node_Array nodeArray;
for(int i = 0 ; i point ; i++){
nodeArray.node[i].count = wCA->wC[i].count;
nodeArray.node[i].word = wCA->wC[i].word ;
nodeArray.node[i].leftChild = NULL;
nodeArray.node[i].rightChild= NULL;
}
nodeArray.point = wCA->point;
return nodeArray;
}
/**
*
* Role: Sort of the specified interval
* |
* Explain: 利用插入排序指定范围,将构建哈夫曼树所需要的结
* 点的数组进行升序排序.(该函数将会被多次调用)
*
* @return: 无
*
*/
void InsertSortSE(struct Node_Array *nA,int start , int end){
if(end - start > 0){
int i,j;
int tmpCount;
char tmpChar;
struct Node *tmpLeft,*tmpRight;
for(i = start + 1 ; i <= end ; i++){
tmpCount = nA->node[i].count;
tmpChar = nA->node[i].word ;
tmpLeft = nA->node[i].leftChild;
tmpRight = nA->node[i].rightChild;
for(j = i ; j > start && nA->node[j-1].count > tmpCount ; j--){
nA->node[j].count = nA->node[j-1].count;
nA->node[j].word = nA->node[j-1].word ;
nA->node[j].leftChild = nA->node[j-1].leftChild;
nA->node[j].rightChild = nA->node[j-1].rightChild;
}
nA->node[j].count = tmpCount;
nA->node[j].word = tmpChar ;
nA->node[j].leftChild = tmpLeft ;
nA->node[j].rightChild= tmpRight;
}
}
}
/**
*
* Role: Copy Array
*
* Explain: 将数组a的指定范围(start~end)赋值给数组b该范围
*
* @return: 无
*
*/
void ArrayCopy(int a[],int b[],int start,int end){
if(end >= 0 && start >= 0 && end - start >= 0){
for(int i = start ; i <= end ; i++){
b[i] = a[i];
}
}
}
/**
*
* Role: Traverse
*
* Explain: 利用先序遍历构建哈夫曼树(根:Root) 并
* 将遍历的结果放在全局变量wCArr(保存字
* 符及其编码的数组)
*
* @return: 无
*
*/
void Traverse(struct Node* Root){
if(Root->leftChild==NULL&&Root->rightChild==NULL){ //已经到了根节点
Root->myAdrr=Pos;//
Root->rgAdrr=0;//
Root->lfAdrr=0;//
Pos+=1;//

wCArr.wCode[wCArr.point].word = Root->word;
ArrayCopy(dyArr.dArray,wCArr.wCode[wCArr.point].code,0,dyArr.point-1);
wCArr.wCode[wCArr.point].point = dyArr.point;
wCArr.point+=1;
dyArr.point-=1;

return;
}

Root->myAdrr=Pos;//
Pos+=1;//

if(Root->leftChild != NULL){
dyArr.dArray[dyArr.point] = 0;
dyArr.point+=1;
Root->lfAdrr=Pos;//
Traverse(Root->leftChild);
}
if(Root->rightChild != NULL){
dyArr.dArray[dyArr.point] = 1;
dyArr.point+=1;
Root->rgAdrr=Pos;//
Traverse(Root->rightChild);
}

dyArr.point-=1;

return ;
}
/**
*
* Role: Traverse
*
* Explain: 纯粹先序遍历树
*
* @return: 无
*
*/
void TreeT(struct Node* Root,int *count,int *max){
if(Root->leftChild==NULL&&Root->rightChild==NULL){ //已经到了根节点
printf("|%10c|%11d|\n",Root->word,Root->count);
printf("+----------+-----------+\n");

if(*max <*count){
*max = *count;
}

(*count)--;
return ;
}

printf("|%10c|%11d|\n",Root->word,Root->count);
printf("+----------+-----------+\n");

if(Root->leftChild){
(*count)++;
TreeT(Root->leftChild,count,max);
}

if(Root->rightChild){
(*count)++;
TreeT(Root->rightChild,count,max);
}

(*count)--;
return ;
}
int Traverset(struct Node* Root){
//开始时间
start =GetTickCount();

printf("Tree visting is working......\n");

printf("+----------+-----------+\n");
printf("| Visit Tree |\n");
printf("+----------+-----------+\n");
printf("| word | count |\n");
printf("+----------+-----------+\n");

if(Root==NULL){
return 0;
}

int count=1;
int max = 0;

TreeT(Root,&count,&max);

//结束时间
stop =GetTickCount();
printf("...Over.....OK...(%lld ms)\n\n",stop-start);

return max;
}
/**
*
* Role: Make a Huffuman Tree
*
* Explain: 根据存储字符频率的结构体数组wCA排序转化
* 为创建哈夫曼树所需要结点数组nodeArray,利
* 用结点数组进行多次排序并且动态增加元素构
* 建哈夫曼树
*
* @return: Root(Huffuman Tree Root)
*
*/
struct Node* HuffumanTreeBuild(struct Word_Count_Array *wCA){
//开始时间
start =GetTickCount();

struct Node_Array nodeArray = InsertSort(wCA); //对统计好的字符频率结构体数组进行排序并将排序放入nodeArray数组中

printf(">>>Building Huffuman tree is working......\n");

struct Node *Root;
for(int i = 1 ; i nodeArray.node[nodeArray.point].count = nodeArray.node[i].count + nodeArray.node[i-1].count;
nodeArray.node[nodeArray.point].leftChild = &(nodeArray.node[i-1]);
nodeArray.node[nodeArray.point].rightChild= &(nodeArray.node[i]) ;
nodeArray.node[nodeArray.point].word='~';

Root = &(nodeArray.node[nodeArray.point]);

nodeArray.point +=1;
InsertSortSE(&nodeArray,i+1,nodeArray.point-1);
if(i+1 == nodeArray.point||i+1 == nodeArray.point - 1){
break;
}
}

//结束时间
stop =GetTickCount();
printf("...Over.....OK...(%lld ms)\n\n",stop-start);

//开始时间
start =GetTickCount();

printf("Encoding is working......\n");

Traverse(Root); //遍历过程中将每个字符类型code编码存储存入全局变量wCArr中

//结束时间
stop =GetTickCount();
printf("...Over.....OK...(%lld ms)\n\n",stop-start);

return Root;
}
/**
*
* Role: Show Huffuman Code
*
* Explain: 显示(存放在全局变量wCA中的)字符编码
*
* @return: 无
*
*/
void ShowHuffumanCode(){
//开始时间
start =GetTickCount();

printf("+----------+---------------------------+\n");
printf("+ Huffuman Code +\n");
printf("+----------+---------------------------+\n");
printf("| word | code |\n");
printf("+----------+---------------------------+\n");

for(int i = 0 ; i char str = wCArr.wCode[i].word;

printf("|%-10c|",str);

int j;
for(j = 0 ; j printf("%d ",wCArr.wCode[i].code[j]);
}

for(int k = 0 ; k <27-2*j ; k++){
printf(" ");
}
printf("|\n");
printf("+--------------------------------------+\n");

}

//结束时间
stop =GetTickCount();
printf("...Over.....OK...(%lld ms)\n\n",stop-start);

}
//辅组二叉树格式二维数组形成 (树枝高度)
int F(int x){
if(x == 1){
return 1;
}else if(x == 2){
return 2;
}
if(x >= 3){
return 2*F(x-1) + 1;
}
return -1;
}
//辅组二叉树格式二维数组形成
int HelpFunc(int x,int base1,int base2,int spare){
if(x == 2){
return base1;
}else if(x == 3){
return base2;
}
if(x > 3){
return 2*HelpFunc(x-1,base1,base2,spare) + spare;
}
return -1;
}
/**
*
* Role: Draw binary tree in console
*
* Explain: 绘制二叉树在控制台
*
* @return: void
*
*/
void PaintBiTree(struct Node* Root){
//开始时间
start =GetTickCount();

int deep = Traverset(Root); //树的深度
int branch; //枝长
int baseW = HelpFunc(deep,4,11,1);//数组宽度{ f(2) = 4 f(3) = 11 f(n) = 2*f(n-1) + 1 (n>=2) }
int deepH = HelpFunc(deep,3,6,0); //数组高度{ f(2) = 3 f(3) = 6 f(n) = 2*f(n-1) (n>=2) }

//printf("deepH = %d baseW = %d\n",deepH,baseW);

struct Node *treeDim[deepH][baseW],*tmpL,*tmpR;

tmpL =(struct Node*)malloc(sizeof(struct Node));
tmpR =(struct Node*)malloc(sizeof(struct Node));
tmpL->word='\\';
tmpR->word='\/';
for(int i = 0 ; i for(int j = 0 ; j treeDim[i][j]=NULL;
}
}

treeDim[0][baseW/2] = Root;


//二叉树格式创建
int floor;
for(int i = 0,floor = 1 ; floor <= deep; floor++,i+=branch+1){
for(int j = 0 ; j if(treeDim[i][j]!=NULL){
if(treeDim[i][j]->leftChild!=NULL){ //左孩子
branch = F(deep - floor );
for(int k = 1 ; k <= branch ; k++){
treeDim[i+k][j-k] = tmpL;
}
treeDim[i+branch+1][j-branch-1] = treeDim[i][j]->leftChild;
}
if(treeDim[i][j]->rightChild!=NULL){ //右孩子
branch = F(deep - floor);
for(int k = 1 ; k <= branch ; k++){
treeDim[i+k][j+k] = tmpR;
}
treeDim[i+branch+1][j+branch+1] = treeDim[i][j]->rightChild;
}
}
}
}

//根据二维数组打印二叉树格式
for(int i = 0 ; i for(int j = 0 ; j if(treeDim[i][j]==NULL){
printf(" ");
}else if(treeDim[i][j]==tmpL){
printf("\/");
}else if(treeDim[i][j]==tmpR){
printf("\\");
}else if(treeDim[i][j]!=NULL){
printf("%c",treeDim[i][j]->word);
}
}
printf("\n");
}

//结束时间
stop =GetTickCount();
printf("...Over.....OK...(%lld ms)\n\n",stop-start);

getchar();
}

/* * * * * * * * * * * * * * * * * * * * * * * *
* *
* Function Module : <> File Operation *
* *
* Explain : 文件操作模块 *
* *
* @author: luewang *
* *
* * * * * * * * * * * * * * * * * * * * * * * */
#include"GlobalVCS.h"
/**
*
* Role: read word from src to buff
*
* Explain: 从文件中读入字符并将其存入buff数组中
*
* @return: buff
*
*/
char* FileInputStream(char* src){
//开始时间
start =GetTickCount();

FILE *file;
char buff[MAX];

if((file = fopen(src,"r"))==NULL){
printf("Error : Open File %s is Faile To Open!!! \n",src);
}

printf(">>>Open File directory is : %s \n",src);

int ch , count;
printf("\n-+-+-+-+-+-+-+Content-+-+-+-+-+-+-+-\n"); //显示从文件中读出的内容
for(count = 0;(ch=fgetc(file))!=EOF;count++){
buff[count] = ch;
printf("%c",ch);
}
printf("\n-+-+-+-+-+-+-+-End+-+-+-+-+-+-+-+-+-+-\n");

//结束时间
stop =GetTickCount();
printf("...Over.....OK...(%lld ms)\n\n",stop-start);

fclose(file);
return buff;
}
/**
*
* Role: file visit and save tree
*
* Explain: 先序遍历保存构建好的哈夫曼树
*
* @return: 无
*
*/
void SaveTreeVisit(struct Node *Root,FILE *file){
if(Root->leftChild==NULL&&Root->rightChild==NULL){ //叶子节点

printf("|%10c|%11d|%12d|%12d|%12d|\n",Root->word,Root->count,Root->myAdrr
,Root->lfAdrr,Root->rgAdrr);
printf("+----------+-----------+------------+------------+------------+\n");

fwrite(Root,sizeof(struct Node),1,file);

return;
}

printf("|%10c|%11d|%12d|%12d|%12d|\n",Root->word,Root->count,Root->myAdrr
,Root->lfAdrr,Root->rgAdrr);
printf("+----------+-----------+------------+------------+------------+\n");

fwrite(Root,sizeof(struct Node),1,file);
SaveTreeVisit(Root->leftChild,file);
SaveTreeVisit(Root->rightChild,file);
}
/**
*
* Role: save huffuman tree to file
*
* Explain: 将根节点是Root的树保存到dir路径文件中.
*
* @return : 无
*
*/
void SaveHuffumanTree(char *dir,struct Node *Root){
//开始时间
start =GetTickCount();

FILE *file;

if((file = fopen(dir,"wb+")) == NULL){
printf("Error : Save File %s is Faile To Open!!! \n",dir);
}
printf(">>>Save File directory is : %s \n",dir);

printf("+----------+-----------+------------+------------+------------+\n");
printf("| word | count | myAdrr | lfAdrr | rgAdrr |\n");
printf("+----------+-----------+------------+------------+------------+\n");

SaveTreeVisit(Root,file);

//结束时间
stop =GetTickCount();
printf("...Over.....OK...(%lld ms)\n\n",stop-start);

fclose(file);
}
/**
*
* Role: File Visit And Get Tree
*
* Explain: 从文件中取出哈夫曼树节点信息放入tmpRoot数组中
* 通过tmpRoot数组中构建哈夫曼树 , tmpRoot数组每
* 个元素存储了左右孩子和自己的地址(int)
*
* @return : tmpRoot头结点(哈夫曼树根结点)
*
*/
struct Node* GetTreeVisit(FILE *file){
int point = 0;
struct Node tmpRoot[N];
while(fread(&tmpRoot[point],sizeof(struct Node),1,file)!=NULL){

if(tmpRoot[point].lfAdrr==0&&tmpRoot[point].rgAdrr==0){
printf("|%10c|%11d|\n",tmpRoot[point].word,tmpRoot[point].count);
printf("+----------+-----------+\n");
}

point+=1;
}

for(int i = 0 ; i if(tmpRoot[i].lfAdrr == 0){
tmpRoot[i].leftChild = NULL;
}else if(tmpRoot[i].lfAdrr != 0){
for(int j = i + 1 ; j if(tmpRoot[j].myAdrr == tmpRoot[i].lfAdrr){
tmpRoot[i].leftChild = &tmpRoot[j];
break;
}
}
}
if(tmpRoot[i].rgAdrr == 0){
tmpRoot[i].rightChild = NULL;
}else if(tmpRoot[i].rgAdrr != 0){
for(int j = i + 1 ; j if(tmpRoot[j].myAdrr == tmpRoot[i].rgAdrr){
tmpRoot[i].rightChild = &tmpRoot[j];
break;
}
}
}
}
return tmpRoot;
}
/**
*
* Role: Get Huffuman Tree
*
* Explain: 从指定(*.dat)文件中获取获取哈夫曼树,给该树
* 根结点Root赋值 .
*
* @return : 无
*
*/
void GetHuffumanTree(char *dir,struct Node **Root){
//开始时间
start =GetTickCount();
FILE *file;

file = fopen(dir,"rb+");
if(file==NULL){
printf("Error : Get File Open is failed To Open : %s\n",dir);
}
printf(">>>Get File directory is : %s \n",dir);

printf("+----------+-----------+\n");
printf("| word | count |\n");
printf("+----------+-----------+\n");

*Root = GetTreeVisit(file); //哈夫曼树根结点

//结束时间
stop =GetTickCount();
printf("...Over.....OK...(%lld ms)\n\n",stop-start);

fclose(file);
}
/**
*
* Role: word zip
*
* Explain: 将指定字符ch根据哈夫曼树编码(wCArr)进行压缩至
* 文件 huffuFile 中.
*
* @return : 无
*
*/
void ZIP(int ch,FILE *huffuFile){
for(int i = 0 ; i if(ch == wCArr.wCode[i].word){
for(int j = 0 ; j
printf("%d",wCArr.wCode[i].code[j]);

fputc(wCArr.wCode[i].code[j]+48,huffuFile);
}
}
}
}
/**
*
* Role: file zip
*
* Explain: 指定文件路径src进行文件压缩至一个新的文
* 件中huffuFile
*
* @return : 无
*
*/
void FileZip(char* src){
//开始时间
start =GetTickCount();

FILE *file,*huffuFile;

if((file = fopen(src,"r+")) == NULL){
printf("Error : File %s Open is failed!!!\n",src);
}
printf(">>>ZIP File directory is : %s \n",src);

char dir[strlen(src)+5];
strcpy(dir,src);
dir[strlen(dir)-4]='\0';
strcat(dir,"_hf.txt");

if((huffuFile = fopen(dir,"w+")) == NULL){
printf("Error : Zipped File %s Open is failed!!!\n",dir);
}
printf(">>>Zipped File directory is : %s \n",dir);

int ch;

printf("\n-+-+-+-fake Binary l stream-+-+-+-+-\n");
while((ch=fgetc(file))!=EOF){
ZIP(ch,huffuFile);
}
printf("\n-+-+-+-+-+-+-+-End+-+-+-+-+-+-+-+-+-\n");

//结束时间
stop =GetTickCount();
printf("...Over.....OK...(%lld ms)\n\n",stop-start);

fclose(file);
fclose(huffuFile);
}
/**
*
* Role: file unzip
*
* Explain: 将指定哈夫曼 0 1 文件(huffuFile)进行哈夫曼树解
* 码存入file文件中
*
* @return : 无
*
*/
void UnZIP(struct Node *Root,FILE *huffuFile,FILE *file){
struct Node *root = Root; //哈夫曼树根结点
int ch;
while((ch=fgetc(huffuFile))!=EOF){
printf("%c",ch);
if(ch - 48 == 0){
root=root->leftChild;
}else if(ch - 48 == 1){
root=root->rightChild;
}

if(root->rightChild==NULL&&root->leftChild==NULL){ //已经到了叶节点
fputc(root->word,file);
root=Root; //回到根节点
}
}
}
/**
*
* Role: file unzip
*
* Explain: 对给定文件路径进行哈夫曼树解压 Root:
* 为哈夫曼树根结点
*
* @return : 无
*
*/
void FileUnZip(char* dir,struct Node *Root){
//开始时间
start =GetTickCount();

FILE *file,*huffuFile;

if((huffuFile = fopen(dir,"r+")) == NULL){
printf("Unzip File Open is failed : %s\n",dir);
}
printf(">>>Unzip File directory is : %s \n",dir);

char Dir[strlen(dir)];
strcpy(Dir,dir);
Dir[strlen(dir)-7]='\0';
strcat(Dir,"`.txt");

printf("After UnZip FIle Is %s\n",Dir);

if((file= fopen(Dir,"w+")) == NULL){
printf("Unzipped File Open is failed : %s\n",Dir);
}
printf(">>>Unzipped File directory is : %s \n",Dir);

UnZIP(Root,huffuFile,file);
printf("\n");

//结束时间
stop =GetTickCount();
printf("...Over.....OK...(%lld ms)\n\n",stop-start);
fclose(file);
fclose(huffuFile);
}


#include
#include
#include
#include
#include"FileOperate.h"
#include"WordHzCount.h"
#include"HuffuTreeBuild.h"
//文件压缩项
void ZIPFILE(char *src){
char dir[strlen(src)+1]; //保存哈夫曼树的文件路径
strcpy(dir,src);
dir[strlen(dir)-4]='\0';
strcat(dir,".dat");

char *buff = FileInputStream(src); //获取指定文件中的资源
struct Word_Count_Array wCA = SingleChar_Hz(buff,strlen(buff));//统计指定资源文件中的字符出现频率
struct Node* Root = HuffumanTreeBuild(&wCA); //构建哈夫曼树Root 并且将字符编码存入全局wCA中
SaveHuffumanTree(dir,Root); //将哈夫曼树存入文件中去
ShowHuffumanCode(); //展示字符编码
PaintBiTree(Root); //展示哈夫曼树

FileZip(src); //文件压缩

}
//文件解压项
void UNZIPFILE(char *dir){
char huffile[strlen(dir)+10]; //保存哈夫曼树的文件路径
strcpy(huffile,dir);
huffile[strlen(huffile)-7]='\0';
strcat(huffile,".dat");

struct Node *root; //哈夫曼树根结点
GetHuffumanTree(huffile,&root);

FileUnZip(dir,root); //文件解压

PaintBiTree(root); //展示哈夫曼树
}
//帮助
void HELP(){
printf("\nYou need to enter two parameters.\n");
printf("The first parameter is the functional option(the following values are available).\n");
printf("'-zip' Or '-unzip' which means decompression and compression.\n");
printf("The second parameter is the filepath option(such as : 'D:\\a.txt').\n");
printf("It is important to note that the input format cannot have any extra Spaces, and the format is '-option' 'path'\n");
}
int main() {

printf("Welcome to Huffman coding by Wang.\nNotice : you can use the '-help' for help.\nLanguage: C \nAuthor : luewang \nVersion : 1.0\n");
char option[N];
char path[N];
while(1){
printf("WHuff>>>");
scanf("%s",option);

if(strcmp(option,"-help")==0){
HELP();
}else if(strcmp(option,"-zip")==0){
scanf("%s",path);
ZIPFILE(path);
}else if(strcmp(option,"-unzip")==0){
scanf("%s",path);
UNZIPFILE(path);
}else if(strcmp(option,"exit")==0){
exit(0);
}else{
printf("Error: Please input the correct format. You can also use '-help' to view the help document\n");
}
}
return 0;
}


推荐阅读
  • 蓝桥杯物联网基础教程:通过GPIO输入控制LED5的点亮与熄灭
    本教程详细介绍了如何利用STM32的GPIO接口通过输入信号控制LED5的点亮与熄灭。内容涵盖GPIO的基本配置、按键检测及LED驱动方法,适合具有STM32基础的读者学习和实践。 ... [详细]
  • NOIP2000的单词接龙问题与常见的成语接龙游戏有异曲同工之妙。题目要求在给定的一组单词中,从指定的起始字母开始,构建最长的“单词链”。每个单词在链中最多可出现两次。本文将详细解析该题目的解法,并分享学习过程中的心得体会。 ... [详细]
  • 在 Linux 环境下,多线程编程是实现高效并发处理的重要技术。本文通过具体的实战案例,详细分析了多线程编程的关键技术和常见问题。文章首先介绍了多线程的基本概念和创建方法,然后通过实例代码展示了如何使用 pthreads 库进行线程同步和通信。此外,还探讨了多线程程序中的性能优化技巧和调试方法,为开发者提供了宝贵的实践经验。 ... [详细]
  • 题目链接: Caninepoetry问题概述:给定一个仅包含小写字母的字符串,允许将任意位置的字符修改为任意其他小写字母。目标是通过最少次数的修改,使字符串中所有长度大于1的子串均满足特定条件。本文详细分析了该问题,并运用思维与贪心算法,提出了一种高效解决方案。通过对字符串的深入解析,我们探讨了如何在最小化修改次数的同时,确保所有子串符合要求。 ... [详细]
  • Presto:高效即席查询引擎的深度解析与应用
    本文深入解析了Presto这一高效的即席查询引擎,详细探讨了其架构设计及其优缺点。Presto通过内存到内存的数据处理方式,显著提升了查询性能,相比传统的MapReduce查询,不仅减少了数据传输的延迟,还提高了查询的准确性和效率。然而,Presto在大规模数据处理和容错机制方面仍存在一定的局限性。本文还介绍了Presto在实际应用中的多种场景,展示了其在大数据分析领域的强大潜力。 ... [详细]
  • 单链表的高效遍历及性能优化策略
    本文探讨了单链表的高效遍历方法及其性能优化策略。在单链表的数据结构中,插入操作的时间复杂度为O(n),而遍历操作的时间复杂度为O(n^2)。通过在 `LinkList.h` 和 `main.cpp` 文件中对单链表进行封装,我们实现了创建和销毁功能的优化,提高了单链表的使用效率。此外,文章还介绍了几种常见的优化技术,如缓存节点指针和批量处理,以进一步提升遍历性能。 ... [详细]
  • 使用 `git stash` 可以将当前未提交的修改保存到一个临时存储区,以便在后续恢复工作目录时使用。例如,在处理中间状态时,可以通过 `git stash` 命令将当前的所有未提交更改推送到一个新的储藏中,从而保持工作目录的整洁。此外,本文还将详细介绍如何解决 `git stash pop` 时可能出现的冲突问题,帮助用户高效地管理代码变更。 ... [详细]
  • 深入解析C语言中的动态规划算法:以背包问题为例
    本文深入探讨了C语言中动态规划算法的应用,以经典的背包问题为例进行详细解析。通过实例分析,展示了如何利用动态规划解决复杂优化问题,并提供了高效的代码实现方法。文章不仅涵盖了算法的基本原理,还讨论了其在实际编程中的应用技巧和优化策略,为读者提供了全面的理解和实践指导。 ... [详细]
  • 寒假作业解析:第三周 2月12日 第7题
    尽快完成之前的练习任务!每日一练2.1 Problem A Laurenty and Shop 的题目要求是选择两条不同的路线以最小化总的等待时间。简要分析:通过对比不同路线的等待时间,可以找到最优解。此问题可以通过动态规划或贪心算法来解决,具体取决于路线的复杂性和约束条件。 ... [详细]
  • 本文对常见的字符串哈希函数进行了全面分析,涵盖了BKDRHash、APHash、DJBHash、JSHash、RSHash、SDBMHash、PJWHash和ELFHash等多种算法。这些哈希函数在不同的应用场景中表现出各异的性能特点,通过对比其算法原理、计算效率和碰撞概率,为实际应用提供了有价值的参考。 ... [详细]
  • 2018年9月21日,Destoon官方发布了安全更新,修复了一个由用户“索马里的海贼”报告的前端GETShell漏洞。该漏洞存在于20180827版本的某CMS中,攻击者可以通过构造特定的HTTP请求,利用该漏洞在服务器上执行任意代码,从而获得对系统的控制权。此次更新建议所有用户尽快升级至最新版本,以确保系统的安全性。 ... [详细]
  • 在前文探讨了Spring如何为特定的bean选择合适的通知器后,本文将进一步深入分析Spring AOP框架中代理对象的生成机制。具体而言,我们将详细解析如何通过代理技术将通知器(Advisor)中包含的通知(Advice)应用到目标bean上,以实现切面编程的核心功能。 ... [详细]
  • 本文介绍了UUID(通用唯一标识符)的概念及其在JavaScript中生成Java兼容UUID的代码实现与优化技巧。UUID是一个128位的唯一标识符,广泛应用于分布式系统中以确保唯一性。文章详细探讨了如何利用JavaScript生成符合Java标准的UUID,并提供了多种优化方法,以提高生成效率和兼容性。 ... [详细]
  • 机器学习中的标准化缩放、最小-最大缩放及鲁棒缩放技术解析 ... [详细]
  • 在Python多进程编程中,`multiprocessing`模块是不可或缺的工具。本文详细探讨了该模块在多进程管理中的核心原理,并通过实际代码示例进行了深入分析。文章不仅总结了常见的多进程编程技巧,还提供了解决常见问题的实用方法,帮助读者更好地理解和应用多进程编程技术。 ... [详细]
author-avatar
人散心未散1
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有