用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字

恋霄愿    -  云代码空间

—— 倾我一生一世恋

哈夫曼编码译码器

2019-03-11|226阅||

摘要:用哈夫曼进行文本压缩

/*-----头文件------*/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <time.h>

#include <windows.h>

#include <conio.h>

#include <malloc.h>

/*----定义宏-----*/

#define MAXNUM 10000

#define SIZE 100

#define ERROR 0

#define TRUE 1

#define OK 1

#define MAX 128             //叶子节点个数(对应ASCII码)

#define MT 2*MAX-1           //树的节点个数

/*-----由动态输入建立哈夫曼树------*/

//哈弗曼树的数据结构

typedef struct HuffmanTNode{

char ch;               // 要编码的字符表示

    unsigned int weight;   // 结点的权值

    unsigned int parent,lchild,rchild;//双亲,左孩子,右孩子

}HuffmanTNode,*Put_HuffmanTree;

typedef char **HuffmanCode; //哈弗曼结点的数据结构

//读文件的哈弗曼树的结构定义

typedef struct HNode{

int weight;  //权值

int parent;  //双亲位置

int LChild;  //左孩子位置

int RChild;  //右孩子位置

}HTNode,HuffmanTree[MT+1];   //结构体数组 (相当与指针)

/*---文件编码的数据结构----*/

typedef struct Node{

char letter;//字符

char* code;//编码

int w;//权值(对应文章中字母(letter)出现次数)

}Huffman[MAX+1];//结构体数组储存权值的顺序存储结构

//定义全局变量

HuffmanTree ht;     //存储哈夫曼树

Put_HuffmanTree HT;                //哈弗曼树(输入构建)

HuffmanCode HC;                   //哈弗数据

Huffman qz;  //权值相关信息

int weight[MT+1] = {0}; //存储临时权值

int t = 0;    //存储

/*********************函数声明**********************/

void select(int *s1,int *s2);//建立哈夫曼树时的选择权值

void Put_Select(int n, int *s1, int *s2);//动态建立哈夫曼树结构的选择算法

int ReadWeight();//从文件中读文章获得权值,返回权值个数

void CrtHuffmanTree();//建立哈夫曼树

int HuffmanCoding(int n);//哈夫曼数(由键盘输入算法)

void Encoding();//编码

void HuffmanCodePrint();//打印

void WriteTree();//向文件中写入哈夫曼树

void Initialization();//初始化

void WriteCode();//向文件中写入编码

void Decoding();//译码

int find_letter(char ch);//查找字符

int find_code(char s[]);//查找编码

void InitTree();//初始化树

void TreePrinting();//打印哈夫曼树

void Menu();//菜单

void putTree_menu();//二级界面

void load();//loading

void Encoding_put(int n);//对字符串进行编码

void Decoding_put(int n);//对编码进行译码

void _print(FILE *fp,HNode hft,int n);

void Writedata_HT(int n)

/*------依次选出两个最小的值-------*/

void Put_Select(int n, int *s1, int *s2){

    int i, ti, t = MAXNUM;

    for(i = 1; i <= n; i++){

        if(!HT[i].parent){

            if(t > HT[i].weight){

                t = HT[i].weight;//t最后为最小的weight

                ti = i;

            }

        }

    }

    *s1 = ti;

    t = MAXNUM;

    ti = 0;

    for(i = 1; i <= n; i++){

        if((!HT[i].parent) && i!=*s1){ //parent为0

            if(t > HT[i].weight){

                t = HT[i].weight;

                ti = i;

            }

        }

    }

    *s2 = ti;

}

 /*------------------编译器的一级菜单--------------------------*/

void Menu(){

InitTree();

printf("********************★欢迎来到哈夫曼编码译码器★************************\n");

printf("|+|■■■■■■■■■■■哈夫曼编码译码器■■■■■■■■■■■■■|+|\n");

printf("|+|■\a\t ★1-请先建立哈夫曼树(文件初始化)\t              \t■|+|\n");

    printf("|+|■  \t ★2-进行编码(根据文件)                     \t   \t■|+|\n");

    printf("|+|■  \t ★3-对其译码(由文件载入编码)\t                  \t■|+|\n");

    printf("|+|■  \t ★4-对哈夫曼编码文件保存打印\t                  \t■|+|\n");

    printf("|+|■  \t ★5-打印哈夫曼树\t                              \t■|+|\n");

    printf("|+|■  \t ★6-进行哈夫曼的一些树操作(键盘输入建立哈夫曼)  \t■|+|\n");

    printf("|+|■\a\t ★7-完成工作请退出\t                            \t■|+|\n");

printf("|+|■\a\t ★8-(附录)打开需要编码的文件进行编辑\t          \t■|+|\n");

    printf("|+|■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■|+|\n");

printf("************************************************************************\n");

}

/*---二级菜单-----*/

void putTree_menu(){

printf("**********************★二级目录菜单★********************************\n");

printf("*================1-★先输入结点和权值建立哈夫曼树====================*\n");

printf("*================2-★显示每个结点的哈弗曼编码========================*\n");

printf("*================3-★输入字符串进行编码并显示保存====================*\n");

printf("*================4-★对编码进行译码并显示保存========================*\n");

  printf("*================5-★将哈夫曼以及编码结果保存到文件data.txt==========*\n");

printf("*================0-★退出操作(退出程序/返回主目录)===================*\n");

printf("**********************************************************************\n");

}

/* ----loading函数--------*/

void load(){

printf("loading");

for(int i=1;i<=5;i++){

printf("...");

Sleep(100);//windows.h下的休眠函数 100 = 0.1秒

}

printf("\n就要进入啦!\n");

Sleep(1000);

}

/*---------初始化树--------*/

void InitTree(){

ht[0].weight = 0;//标志哈夫曼树是否存在

qz[0].w = 0; //标志是否编码

}

/*---------哈夫曼算法创建哈夫曼树--------*/

int HuffmanCoding(int n){

    int i,s1,s2;

    int w[n+1];//weight 0下标不使用

    char title;//标志位

    char ch[n+1];//由键盘输入的要编码的字符

    while(n <= 1){

     printf("输入的数据有误,请重新输入:\n");

     scanf("%d",&n);

}

    int m = 2 * n - 1;

    while(title = getchar() != '\n');//空格后停止输入

printf("■请输入各字符(用空格分开):");

    for(i=1; i<=n; i++){

        scanf("%c",&ch[i]);

        getchar();

    }

    printf("■请输入各权值(用空格分开):");

    for(i = 1; i <= n; i++){

        scanf("%d",&w[i]);

        getchar();

}

    HT = (Put_HuffmanTree)malloc((m+1)*sizeof(HTNode));//0号节点不使用

    for(i = 1 ; i <= n ; i++){

     HT[i].ch = ch[i];

        HT[i].weight = w[i];

        HT[i].parent = 0;

        HT[i].lchild = 0;

        HT[i].rchild = 0;

    }

    for(  ; i <= m ; i++){

     HT[i].ch = '#';//其它中间生成的结点用#表示

     HT[i].weight = 0;

        HT[i].parent = 0;

        HT[i].lchild = 0;

        HT[i].rchild = 0;

    }

    for(i = n+1 ; i <= m ; i++){

        Put_Select(i-1,&s1,&s2);

        HT[s1].parent = i;

        HT[s2].parent = i;

        HT[i].lchild = s1;

        HT[i].rchild = s2;

        HT[i].weight = HT[s1].weight + HT[s2].weight;

    }

    printf("\n■生成的哈夫曼树为(其中生成树时生成的结点用“# ”表示):");

printf("\n");

    printf("char  weight  parent  lchild  rchild\n");

    for(i = 1; i <= m; i++){

        printf("%2c %5d %7d %7d %7d\n", HT[i].ch,  HT[i].weight,  HT[i].parent,  HT[i].lchild,  HT[i].rchild);

    }

    return OK;

}

/*------从叶子到根逆向求每个字符的哈夫曼编码 -------*/

void HuffmanCoding_print(int n){

int i = 0;

int m = 2 * n - 1 ;

HC = (HuffmanCode)malloc((n+1) * sizeof(char*));//分配n个字符编码的头指针向量

if(HC == NULL){

        printf("动态分配内存失败!!!");

}

char *cd;

    cd = (char *)malloc(n * sizeof(char));//分配求编码的工作空间

    cd[n-1] = '\0';//编码结束符

    printf("■其编码表为:\n");

    int c,f,start;

    for(i = 1 ; i <= n ; i++){//逐个字符求哈夫曼编码

        start = n - 1;//编码结束符的位置

        for(c = i ,f = HT[i].parent ; f != 0 ; c = f,f = HT[f].parent){

            if(HT[f].lchild == c){

                cd[--start] = '0';

            }else{

                cd[--start] = '1';

            }

        }

        HC[i] = (char *)malloc((n - start)*sizeof(char)); //为第i个字符编码分配空间

        strcpy(HC[i] , &cd[start]);//从cd复制编码(串)到HC

        printf("其结点为%c的编码为:", HT[i].ch);

        puts(HC[i]);

    }

    free(cd);//释放工作空间

}

/*--------------无栈非递归遍历哈夫曼树求哈夫曼编码-----------*/

/*int HuffmanCoding_print(int n){

int cdlen = 0 , p ,i;

int m = 2 * n - 1;

p = m;

char *cd;

for(i = 1;i <= m;++i){

HT[i].weight = 0;

}

while(p){

if(HT[p].weight == 0){

HT[p].weight = 1;

if(HT[p].lchild != 0){

p = HT[p].lchild;

cd[cdlen++] = '0';

}else if(HT[p].rchild == 0){

HC[p] = (char*)malloc((cdlen+1)*sizeof(char));

cd[cdlen] = '\0';

strcpy(HC[p] , cd);

}

}else if(HT[p].weight == 1){

HT[p].weight == 2;

if(HT[p].rchild != 0){

p = HT[p].rchild;

cd[cdlen++] = '1';

}

}else{

HT[p].weight = 0;

p = HT[p].parent;

--cdlen;

}

}

printf("其结点为%c的权值为:",HT[i].ch,HC[i]);

return OK;

} */

/*---------对字符串进行编码-------------*/

void Encoding_put(int n){

char *s,title,m;

int i ,j , x;

FILE *fp_Ec;

printf("请确定字符串的长度m:");

scanf("%d",&m);

s = (char *)calloc(m , sizeof(char));

if(s == NULL){

printf("为字符串s内存分配失败!!!");

getchar();

exit(0);

}

int len = (int)(sizeof(s)/sizeof(s[0]));

printf("字符串的长度为:%d",len);

while(title = getchar() != '\n');//使其回车可退出循环

printf("\n\a请输入字符串:\n");

for(i = 0;i < len;i++){

scanf("%s",&s[i]);

}

printf("编码结果为:\n");

    for(i = 0;s[i] != '\0'&&i < len;i++){

        for(j = 1;j <= n;j++){

            if(s[i] == HT[j].ch){

                //printf("%s", HC[j]);

                puts(HC[j]);

                continue ;

            }

        }

    }

    if((fp_Ec = fopen("F:\\HuffmanTree\\Ec_putingFile.txt","wb+")) == NULL){

     printf("Ec_puingFile打开失败,请确认文件是否出错!!!");

     getch();

     exit(0);

}else{

printf("文件打开成功现将编码载入文件:");

fprintf(fp_Ec , "\n编码结果为:");

for(i = 0;s[i] != '\0'&&i < len;i++){

        for(j = 1;j <= n;j++){

            if(s[i] == HT[j].ch){

                fprintf(fp_Ec ,"%s",HC[j]);

                //fputs(HC[j] , fp_Ec);

                continue ;

            }

        }

    }

}

fclose(fp_Ec);

printf("是否要查看编码!0-否/1-是");

scanf("%d",&x);

if(x == 1){

if((fp_Ec = fopen("F:\\HuffmanTree\\Ec_putingFile.txt","r")) == NULL){

printf("Ec_puingFile打开失败,请确认文件是否出错!!!");

         getch();

         exit(0);

}else{

char ch0;

ch0 = fgetc(fp_Ec);

while(ch0 != EOF){

putchar(ch0);

ch0 = fgetc(fp_Ec);

}

}

}

fclose(fp_Ec);


    printf("\n");

}

/*---------对编码后的字符串进行译码--------*/

void Decoding_put(int n){

    char s[SIZE], title;

    int i = 0, p = 2*n-1 ,y;//p在根节点位置;

    FILE *fp_Dc;

    while(title = getchar() != '\n');

    printf("\a\n■请输入编码(编码中间无空格):\n");

    scanf("%s", s);

    printf("■输出译码结果为:\n");

    for(i = 0; s[i] != '\0'; i++){

        if(s[i]=='0')

           p=HT[p].lchild;

        if(s[i]=='1')

          p=HT[p].rchild;

        if(p<=n){

           printf("%c", HT[p].ch);

            p=2*n-1;

        }

    }

    if((fp_Dc = fopen("F:\\HuffmanTree\\Dc_putingFile.txt","wb+")) == NULL){

     printf("Dc_puingFile打开失败,请确认文件是否出错!!!");

     getch();

     exit(0);

}else{

printf("\n文件打开成功现将译码载入文件:");

fprintf(fp_Dc , "\n译码结果为:");

for(i = 0; s[i] != '\0'; i++){

            if(s[i]=='0')

                p=HT[p].lchild;

            if(s[i]=='1')

                p=HT[p].rchild;

            if(p<=n){

                fprintf(fp_Dc , "%c",HT[p].ch);

                p=2*n-1;

            }

        }

}

fclose(fp_Dc);

printf("是否要查看编码!0-否/1-是");

scanf("%d",&y);

if(y == 1){

if((fp_Dc = fopen("F:\\HuffmanTree\\Dc_putingFile.txt","r")) == NULL){

printf("Dc_puingFile打开失败,请确认文件是否存储出错!!!");

         getch();

         exit(0);

}else{

char ch0;

ch0 = fgetc(fp_Dc);

while(ch0 != EOF){

putchar(ch0);

ch0 = fgetc(fp_Dc);

}

}

}

fclose(fp_Dc);

     printf("\n");

}

/*------树的初始化-------*/

void Initialization(){

ht[0].weight = 1; //初始化标志,说明哈夫曼树以存在

t=ReadWeight(); //读取权值

CrtHuffmanTree(); //建立哈夫曼树

WriteTree(); //将哈夫曼树写入文件

printf("哈弗曼树'初始化'成功!\n");

}

/*------将哈夫曼树写入文件-------*/

void WriteTree(){

FILE *fp;//hfmTree 文件指针

int m = 2*t-1;

int i;

 

//打开文件

if((fp=fopen("F:\\HuffmanTree\\huffmanTreeopen.txt","w")) == NULL){

printf("open huffmanTreeopen.txt--file error\n");

exit(0);

}//else printf("open huffmanTreeopen.txt--file sucess!\n");

//哈夫曼树写入文件

for(i=1;i<=m;i++)

fprintf(fp,"%d %d %d %d\n",ht[i].weight,ht[i].parent,ht[i].LChild,ht[i].RChild);

//关闭文件

if(fclose(fp)){

printf("\a close huffmanTreeopen.txt--file error!\n");

exit(0);

}//else printf("close huffmanTreeopen.txt--file success!\n");

}

/*-----------选择s1,s2-----------*/

void select(int n,int *s1,int *s2){

int i,min;

//寻找一个没有双亲的节点,找到后退出循环

for(i=1; i<=n; i++){

if(ht[i].parent == 0){

min = i;

break;

}

}

//寻找最小无双亲节点

for(i=1; i<=n; i++){

if(ht[i].weight<ht[min].weight && ht[i].parent == 0)

min = i;

}

*s1 = min;

//寻找次最小无双亲节点

for(i=1; i<=n; i++){

if(ht[i].parent == 0 && i != *s1){

min = i;

break;

}

}

for(i=1; i<=n; i++){

if(ht[i].weight < ht[min].weight && i != *s1 && ht[i].parent == 0)

min = i;

}

*s2 = min;

 

}

/*-----读取文章,获取权值--------*/

int ReadWeight(){

//返回权值个数

int n=1;

FILE *fp;

char ch;

 

//打开文件

if((fp=fopen("F:\\HuffmanTree\\huffmanToBeTran.txt","r")) == NULL){

printf("\a open huffmanToBeTran.txt--file error!\n");

exit(0);

}//else printf("open huffmanToBeTran.txt--file sucess!\n");

 

//读取字符

while(!feof(fp)){//一直循环,知道文件结束

ch = fgetc(fp);

if(ch != EOF){

weight[ch]++;//依次读取字符增加权值

}

}

 

//关闭文件

if(fclose(fp)){

printf("\a close huffmanToBeTran.txt--file error!\n");

exit(0);

}//else printf("close huffmanToBeTran.txt--file success!\n");

 

//临时权值转化到qz[]中

for(int i=0;i<MT;i++){

//printf("%d ",weight[i]);

if(weight[i]>=1){

qz[n].letter = (char)i;

qz[n].w = weight[i];

n++;

}

}

return n-1;//n从1开始计数

}

 

/*----建立哈夫曼树--------*/

void CrtHuffmanTree(){

int i,s1,s2,m = 2*t-1;

//*初始化*//

for(i=1; i<=t; i++){//第1到n个位置放置n个叶子节点

ht[i].weight = qz[i].w;

ht[i].parent = ht[i].LChild = ht[i].RChild = 0;

}

for(i=t+1;i<=m;i++){//第n+1个到第m个位置放置非叶子节点

ht[i].weight = ht[i].parent = ht[i].LChild = ht[i].RChild = 0;

}

//*建立*//

for(i=t+1; i<=m; i++){

select(i-1,&s1,&s2);

//printf("s1 = %d,s2 = %d\n",s1,s2);

ht[i].weight = ht[s1].weight + ht[s2].weight;

ht[s1].parent = ht[s2].parent = i;

ht[i].LChild = s1;

ht[i].RChild = s2;

}

 

}

/*------哈夫曼编码 ---------*/

void Encoding(){

if(ht[0].weight == 0){

printf("没初始化!!\n");

Sleep(2000);//挂起一段时间

return;

}

int i,start,c,p;

char *cd;

cd = (char*)malloc(t*sizeof(char));

cd[t-1]='\0';

for(i=1; i<=t; i++){//对n个叶子节点进行编码

start = t-1;//定位到临时编码数组的最后一位

c = i;//记录当前节点位置

p = ht[i].parent;//记录当前节点的双亲位置

while(p!=0){

--start;

if(ht[p].LChild == c)//若该节点是其双亲的左孩子,则编码0

cd[start]='0';

else//若为右孩子则编码1

cd[start]='1';

c = p;//下次循环的准备条件

p = ht[p].parent;

}

qz[i].code=(char*)malloc((t-start)*sizeof(char));

strcpy(qz[i].code,&cd[start]);

}

free(cd);

//以上代码完成编码工作

/*测试代码

for(i=1;i<=n;i++)

printf("%c %d %s\n",hc[i].letter,hc[i].w,hc[i].code);*/

//将编码写入文件

WriteCode();

/*for(i=1;i<=n;i++){

printf("%s\n",hc[i].code);

}*/

qz[0].w = 1;//标志以编码

printf("编码成功啦……^&^!\n");

}

 

/*-----编码写入的函数---------*/

void WriteCode(){

FILE *fp_code,*fp_text;

char ch;

int i;

//打开编码存储文件

if((fp_code=fopen("F:\\HuffmanTree\\HuffmanTreeCode.txt","w")) == NULL){

printf("\a open HuffmanTreeCode.txt--file error !\n");

exit(0);

}//else printf("open HuffmanTreeCode.txt--file success!\n");

 

//打开需要编码的文本文件

if((fp_text=fopen("F:\\HuffmanTree\\huffmanToBeTran.txt","r")) == NULL){

printf("\a open huffmanToBeTran.txt ……file error !\n");

exit(0);

}//else printf("open huffmanToBeTran.txt--file success!\n");

 

while(!feof(fp_text)){

ch = fgetc(fp_text);

//printf("%c ",ch);

i = find_letter(ch);

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

if(i!=0)

fprintf(fp_code,"%s ",qz[i].code);

}

 

//关闭文件

if(fclose(fp_code)){

printf("\a close HuffmanTreeCode.txt--file error!\n");

exit(0);

}//else printf("close HuffmanTreeCode.txt--file success !\n");

if(fclose(fp_text)){

printf("\a close huffmanToBeTran.txt--file error!\n");

exit(0);

}//else printf("close huffmanToBeTran.txt--file success !\n");

}

 

/*------查找字符*--------*/

int find_letter(char ch){

int low,high,i;

low = 1;high = t;

//二分查找

while(high - low >= 0){

i=(low+high)/2;

if(qz[i].letter == ch)

return i;

else if(qz[i].letter < ch){

low = i+1;

}

else

high = i-1;

}

return 0;

}

/*-------打印哈夫曼树的节点权值---------*/

void PrintHuffmanCode(){

if(ht[0].weight == 0){

printf("没初始化!\n");

Sleep(2000);//挂起一段时间

return;

}

if(qz[0].w == 0){

printf("检测到没有编码!!,请先编码\n");

Sleep(2000);

return;

}

int i=0;

char code[100];

FILE *fp_r,*fp_w;

if((fp_r=fopen("F:\\HuffmanTree\\HuffmanTreeCode.txt","r")) == NULL){

printf("\a open HuffmanTreeCode.txt--file error!\n");

exit(0);

}//else printf("open HuffmanTreeCode.txt success!\n");

if((fp_w=fopen("F:\\HuffmanTree\\CodePrint.txt","w")) == NULL){

printf("\a open CodePrint.txt--file error!\n");

exit(0);

}//else printf("open CodePrint.txt success!\n");

while(!feof(fp_r)){

fscanf(fp_r,"%s\n",code);

printf("%s ",code);

fprintf(fp_w,"%s",code);

i++;

if(i%5 == 0){

printf("\n");

fprintf(fp_w,"\n");

}

}

printf("打印成功啦…………!\n");

}

 

/*-------译码---------*/

void Decoding(){

if(ht[0].weight == 0){

printf("没初始化!\n");

Sleep(2000);//挂起一段时间

return;

}

if(qz[0].w == 0){

printf("检测到没有编码!!\n");

Sleep(2000);//挂起一段时间

return;

}

char code[100];

FILE *fp_r,*fp_w;

int i;

//打开CodeFile.txt文件,从中读取编码

if((fp_r=fopen("F:\\HuffmanTree\\CodePrint.txt","r")) == NULL){

printf("\a open HuffmanTreeCode.txt--file error!\n");

exit(0);

}//else printf("open HuffmanTreeCode.txt success!\n");

 

//打开TextFile.txt文件,存储翻译的内容

if((fp_w=fopen("F:\\HuffmanTree\\TextFile.txt","w")) == NULL){

printf("\a open TextFile.txt--file error!\n");

exit(0);

}//else printf("open TextFile.txt success!\n");

 

while(!feof(fp_r)){

fscanf(fp_r,"%s\n",code);

i = find_code(code);

if(i!=0)

fprintf(fp_w,"%c",qz[i].letter);

}

if(fclose(fp_r)){

printf("\a close HuffmanTreeCode.txt--file error!\n");

exit(0);

}//else printf("close HuffmanTreeCode.txt--file success !\n");

if(fclose(fp_w)){

printf("\a close TextFile.txt--file error!\n");

exit(0);

}//else printf("close TextFile.txt--file success !\n");

printf("恭喜你T^ _ ^T'译码'成功啦!\n");

}

/*-------查找编码------*/

int find_code(char s[]){

int i;

for(i=1;i<=t;i++){

if(strcmp(qz[i].code,s) == 0)

return i;

}

return 0;

}

/*-------打印树-----------*/

void TreePrinting(){

if(ht[0].weight == 0){

printf("没初始化!,请重试\n");

Sleep(2000);//挂起一段时间

return;

}

FILE *fp;

int i,r=t*2-1;

//打开文件

if((fp=fopen("F:\\HuffmanTree\\huffmanTreeprint.txt","w")) == NULL){

printf("\aopen HuffmanTreeCode.txt--file error !\n");

exit(0);

}

for(i=1;i<=r;i++){

if(ht[i].parent == 0)

break;

}

//printf("%d\n",ht[i].parent );

_print(fp,ht[i],0);

if(fclose(fp)){

printf("\aclose huffmanTreeprint.txt--file error!\n");

exit(0);

}

printf("打印成功啦!^*_*^\n");

}

/*-----哈夫曼树纵向显示并写入文件------*/

void _print(FILE *fp,HNode hft,int n){

if(hft.LChild == 0 && hft.RChild == 0){

for(int i=0;i<n;i++){

printf(" ");

fprintf(fp," ");

}

printf("%-6d\n",hft.weight);

fprintf(fp,"%-6d\n",hft.weight);

return ;

}

_print(fp,ht[hft.RChild],n+2);

for(int i=0;i<n;i++){

printf(" ");

fprintf(fp," ");

}

printf("%-6d\n",hft.weight);

fprintf(fp,"%-6d\n",hft.weight);

_print(fp,ht[hft.LChild],n+2);

}

/*------写入数据到文件(动态保存)-------*/

void Writedata_HT(int n){

FILE *fp_ht;

char ch;

int i,j;

char ch1;

int m = 2 * n - 1;

if((fp_ht = fopen ("F:\\HuffmanTree\\data.txt","w")) == NULL){

printf("open data.txt--file error !\n");

getchar();

exit(0);

}else{

fprintf(fp_ht , "动态建立的树为(其中生成树时生成的结点用“# ”表示):\n");

fprintf(fp_ht , "char  weight  parent  lchild  rchild\n");

    for(i = 1; i <= m; i++){

    fprintf(fp_ht , "%2c %5d %7d %7d %7d\n", HT[i].ch,  HT[i].weight,  HT[i].parent,  HT[i].lchild,  HT[i].rchild);

    }

    HC = (HuffmanCode)malloc((n+1) * sizeof(char*));

    char *cd;

        cd = (char *)malloc(n * sizeof(char));

        cd[n-1] = '\0';//编码结束符

    fprintf(fp_ht , "■其编码本内容为:\n");

    fprintf(fp_ht , "■编码表为:\n");

        int c,f,start;

        for(i = 1 ; i <= n ; i++){//逐个字符求哈夫曼编码

        start = n - 1;//编码结束符的位置

        for(c = i ,f = HT[i].parent ; f != 0 ; c = f,f = HT[f].parent){

            if(HT[f].lchild == c){

                cd[--start] = '0';

            }else{

                cd[--start] = '1';

            }

        }

        HC[i] = (char *)malloc((n - start)*sizeof(char)); //为第i个字符编码分配空间

        strcpy(HC[i] , &cd[start]);//从cd复制编码(串)到HC

        fprintf(fp_ht , "其结点为%c的编码为:",HT[i].ch);

        fputs(HC[i] , fp_ht);

        }

    HuffmanCoding_print(n);

    printf("\n将其保存至文件data.txt");

    }

if(fp_ht != NULL){

printf("\n文件保存成功!!!");

}

fclose(fp_ht);

if((fp_ht = fopen("F:\\HuffmanTree\\data.txt","r")) == NULL){

printf("文件保存失败无法打开!!!");

getch();

exit(0);

}else{

ch1 = fgetc(fp_ht);

while(ch1 != EOF){

putchar(ch1);

ch1 = fgetc(fp_ht);

}

printf("\n");

}

fclose(fp_ht);


}

/*----------主函数------------*/

int main()

{

char chose;//主菜单的选择值

char sh , title;

    int n,i,x,T;

system("CLS");//运行前清屏

system("color FD");//设置颜色

load();//等待函数

flag: //设置一个返回标记

     system(“color F4”);

     printf(“在编码前需要将哈夫曼初始化喔!!!”);

     system("color FD");//把颜色改回来

Menu();//调用菜单,完成一系列工作

do{

printf("\a请选择如下的操作:");

         fflush(stdin);

scanf("%c",&chose);

getchar();//除去回车

switch(chose){

case '1':Initialization();break; //初始化

case '2':Encoding();break;    //对叶子节点进行编码

case '3':Decoding();break;   //译码

case '4':PrintHuffmanCode();break;  //打印编码

case '5':TreePrinting();break; //打印哈夫曼树

case '6':

            do{

             putTree_menu();

     printf("请选择进行的二级目录操作: ");

                 scanf("%c",&sh);

                 printf("\n操作结果如下(T^__^T):\n");

                 switch(sh){

                     case '1':

                     printf("请输入要进行操作的数n(n>0):");

                     scanf("%d",&n);

                     HuffmanCoding(n);

                     break;

                 case '2':

    HuffmanCoding_print(n);

break;

                 case '3':

                  Encoding_put(n);

                     break;

                 case '4':

                  Decoding_put(n);

                       break;

case '5':

Writedata_HT(n);

break;

                   case '0':

        printf("完成任务(T_T)准备退出二级目录...\n");

Sleep(500);

printf("\t\n退出二级目录程序……谢谢使用!!!\n");

printf("\a请选择直接退出(1)或返回主目录(0):");

scanf("%d",&T);

if(T == 0){ system("CLS");  goto flag;}//运用goto语句返回主菜单

if(T == 1){ exit(-1); }

break;

                }

        }while(sh != 0 && scanf("%c",&sh) != EOF);

        break;

case '7':

printf("马上为您退出了....!请稍后\n");//退出提醒

Sleep(500);                     //挂起0.5s

exit(0); //退出

break;

case '8':

    system("Type F:\\HuffmanTree\\huffmanToBeTran.txt");//可以用文件指针追加填加一个能编辑文本的操做,用while(ch!=’#’)来填加字符

break;

default:printf("选错啦,再试试吧!\n");

}

}while(scanf("%c",&chose) != EOF);

system("PAUSE");

return 0;

}

顶 1踩 0收藏
文章评论
    发表评论

    个人资料

    • 昵称: 恋霄愿
    • 等级: 中级程序员
    • 积分: 130
    • 代码: 0 个
    • 文章: 1 篇
    • 随想: 0 条
    • 访问: 4 次
    • 关注

    人气文章

    人气代码

      最新提问

        站长推荐