Fork me on GitHub

2019.6.24-2019.6.28(实训数据结构)4.树和二叉树应用项目

2019.6.24-2019.6.28(实训数据结构) 书籍:《数据结构项目实训教程》 赵君喆,戴文华

6.3树和二叉树应用项目

输入一串字符,建立哈夫曼树,然后编码解码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<algorithm>
using namespace std;

char A[50]={};

//构建哈夫曼树结点,包含权重,父节点,左孩子和右孩子 
typedef struct{
    int weight;
    int parent,lchild,rchild;
}HTNode,*HuffmanTree;

typedef char **HuffmanCode;

//计算不同字符的个数
void Calculate_weight(char a[],char b[],int m,int n,int *w){
    int i,j;
    for(i=0;i<n;i++){
        for(j=0;j<m;j++){
            if(b[i]==a[j]){
                A[i+1]=w[i+1]++;
            }
        }
    }
} 

//找到最小的两个结点 
void FindNode(HuffmanTree HT,int n,int &t1,int &t2){
    //构建哈夫曼二叉树 
    HT[0].weight=100;
    t1=0;
    t2=0;
    for(int i=1;i<=n;i++){
        if(HT[i].parent==0){
            if(HT[i].weight<HT[t2].weight){
                if(HT[t2].weight<HT[t1].weight){
                    t1=t2;
                }
                t2=i;
            }
            else if(HT[i].weight<HT[t1].weight){
                t1=t2;
                t2=i;
            }
        }
    } 
} 

//将Huffman二叉树的结构写入output_tree_info.txt
void output_tree_info(HuffmanTree HT,int m){
    //将Huffman二叉树的结构表存入文件 output_tree_info.txt
    int i;
    //写入output_tree_info.txt
    ofstream outfile("output_tree_info.txt");
    outfile<<"编号 权重 父结点 左孩子 右孩子"<<endl;
    for(i=1;i<=m;i++){
        outfile<<i<<"\t";
        outfile<<HT[i].weight<<"\t";
        outfile<<HT[i].parent<<"\t";
        outfile<<HT[i].lchild<<"\t";
        outfile<<HT[i].rchild<<endl;
    } 
}

//将Huffman编码表写入output_code_info.txt 
void output_code_info(char b[],HuffmanCode HC,int n){
    //将Huffman编码表写入output_code_info.txt
    int i;
    //写入output_code_info.txt
    ofstream outfile("output_code_info.txt");
    outfile<<"编码表:"<<"\t"<<"编码频度"<<endl;
    for(i=1;i<=n;i++){
        outfile<<b[i-1]<<":"<<HC[i]<<"\t"<<A[i]+1<<endl;
    } 
}

//为哈夫曼二叉树进行编码,构造Huffman二叉树HT,并求出n个字符的哈夫曼二叉树 
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n){
    //用w存放n个字符的权值,构造哈夫曼树HT
    //并求出n个字符的哈夫曼编码HC
    int m,i,t1,t2,start;
    unsigned c,f;
    HuffmanTree p;
    char *cd;
    m=2*n-1;

    HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
    for(p=HT+1,i=1;i<=n;i++){//前n个结点初始化 
        p->weight=w[i];
        p->parent=0;
        p->lchild=0;
        p->rchild=0; 
    } 
    for(;i<=m;i++,p++){//第n+1个顶点到2n-1个顶点初始化 
        p->weight=0;
        p->parent=0;
        p->lchild=0;
        p->rchild=0;
    }
        
    for(i=n+1;i<=m;i++){//构建哈夫曼树 
        FindNode(HT,i-1,t1,t2);
        HT[t1].parent=i;
        HT[t2].parent=i;
        HT[i].lchild=t1;
        HT[i].rchild=t2;
        HT[i].weight=HT[t1].weight+HT[t2].weight;
    }
    output_tree_info(HT,m);//将树结构写入文件
    //求每个字符的哈夫曼编码(从叶子结点到根结点逆向进行)
    HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
    cd=(char*)malloc(n*sizeof(char));//分配求编码的工作空间
    cd[n-1]='\0';//编码结束符
    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';
            }
        } 
        //为第i个字符分配空间
        HC[i]=(char*)malloc((n-start)*sizeof(char)) ;
        strcpy(HC[i],&cd[start]);//从cd复制编码串到HC中 
    } 
    free(cd);//释放空间 
}

void Output_HuffmanCoding(char a[],char b[],int m,int n,HuffmanCode HC){
    //输出Huffman编码
    int i,j;
    printf("字符串转换成的Huffman编码如下:\n");
    for(i=0;i<m;i++){
        for(j=0;j<m;j++){
            if(a[i]==b[j]){
                cout<<HC[j+1]<<"\t";
            }
        }
    } 
    cout<<endl;
} 

void HuffmanDecoding(int n,char b[],HuffmanTree HT){
    //对编码的二进制串进行解码 
    int m=2*n-1;
    int i=m;
    char c;
    printf("\n请输入一串编码:\n");
    cin>>c;
    while((c=='0')||(c=='1')){//判断是否是合法字符 
        if(c=='0')
            i=HT[i].lchild;//继续向左查找
        else
            i=HT[i].rchild;//继续向右查找
        if(HT[i].lchild==0){//直到分支的末端 
        printf("\n所得译码为:\n");
            printf("%c\n",b[i-1]);//输出对应的符合
            i=m;//重新开始找下一个 
        } 
        cin>>c;
    } 
    printf("\n");
} 

int main(){
    HuffmanTree HTree;
    HuffmanCode HCode; 
    char a[100],b[100]; //a为输入的字符串 
    int i=0,j=0,len=0,n=0,*w;
    printf("请输入任意一组字符:\n");
    gets(a);
    len=strlen(a);
    for(i=0;i<len;i++){
        for(j=0;j<i;j++){
            if(i<len&&a[j]==a[i]){
                i++;
                j=-1;
            } 
        }
        if(i<len){
            b[n]=a[i];
            n++;
        }
    }
    w=(int*)malloc((n+1)*sizeof(int));
    for(i=1;i<=n;i++){ //初始化 
        w[i]=0;
    } 
    cout<<"----"<<endl;
    Calculate_weight(a,b,len,n,w);//计算不同字符的个数 
    cout<<"---"<<endl;
    HuffmanCoding(HTree,HCode,w,n);//构造Huffman二叉树HT 
    output_code_info(b,HCode,n);
    printf("\nHuffman各个字符的详细编码如下:\n");
    printf("编码表:\t编码频度:\n");
    for(i=1;i<=n;i++){
        cout<<b[i-1]<<":"<<HCode[i]<<"\t"<<A[i]+1<<endl;
    }
    Output_HuffmanCoding(a,b,len,n,HCode);//输出Huffman编码
    HuffmanDecoding(n,b,HTree);//对编码的二进制串进行解码 
    return 0;
} 

 

posted @ 2019-06-27 10:41  &#127808;&#127808;&#127808;  阅读(274)  评论(0编辑  收藏  举报
🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀 🍀