热门标签 | 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;
}


推荐阅读
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文总结了在开发中使用gulp时的一些技巧,包括如何使用gulp.dest自动创建目录、如何使用gulp.src复制具名路径的文件以及保留文件夹路径的方法等。同时介绍了使用base选项和通配符来保留文件夹路径的技巧,并提到了解决带文件夹的复制问题的方法,即使用gulp-flatten插件。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • Day2列表、字典、集合操作详解
    本文详细介绍了列表、字典、集合的操作方法,包括定义列表、访问列表元素、字符串操作、字典操作、集合操作、文件操作、字符编码与转码等内容。内容详实,适合初学者参考。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 在2022年,随着信息化时代的发展,手机市场上出现了越来越多的机型选择。如何挑选一部适合自己的手机成为了许多人的困扰。本文提供了一些配置及性价比较高的手机推荐,并总结了选择手机时需要考虑的因素,如性能、屏幕素质、拍照水平、充电续航、颜值质感等。不同人的需求不同,因此在预算范围内找到适合自己的手机才是最重要的。通过本文的指南和技巧,希望能够帮助读者节省选购手机的时间。 ... [详细]
  • 手把手教你使用GraphPad Prism和Excel绘制回归分析结果的森林图
    本文介绍了使用GraphPad Prism和Excel绘制回归分析结果的森林图的方法。通过展示森林图,可以更加直观地将回归分析结果可视化。GraphPad Prism是一款专门为医学专业人士设计的绘图软件,同时也兼顾统计分析的功能,操作便捷,可以帮助科研人员轻松绘制出高质量的专业图形。文章以一篇发表在JACC杂志上的研究为例,利用其中的多因素回归分析结果来绘制森林图。通过本文的指导,读者可以学会如何使用GraphPad Prism和Excel绘制回归分析结果的森林图。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
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社区 版权所有