哈弗曼编码

来源:互联网 发布:北京的设计公司知乎 编辑:程序博客网 时间:2024/06/08 19:07
#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>using namespace std;typedef struct{   char ch;   int weight;   int lchild,rchild,parents;}HNode,*HLink;typedef char **Haffmancode;char b[1000];int kinds;int deciph = 1;HLink Hc;Haffmancode Hccode;void coding();void decipher();void minterface();void showthecode();Haffmancode Haffmanbuilt(HLink &Hc);staticint a[256];void clrscr(){    system("cls");}void Dataread(char *mingwen){    char c;    int k = 0, i, tim = 1;    getchar();    while((c = getchar()) != '#')    {        if(tim && deciph)            for(tim = 0, i = 0; i < 256; i++)                  a[i] = 0;        mingwen[k++] = c;        if(deciph)             a[c]++;    }    if(deciph){        Hccode = Haffmanbuilt(Hc);        showthecode();    }    mingwen[k] = '\0';}Haffmancode Haffmanbuilt(HLink &Hc){    int i, n = 0, m, t = 0, start;    Haffmancode Hccode;    kinds = 0;    for(i = 0; i < 256; i++)        if(a[i])           kinds++;    start = kinds + 1;    m = 2 * kinds - 1;    Hc = (HLink)malloc((m+1) * sizeof(HNode));    for(i = 0; i < 256; i++)    {        if(a[i]){            b[++t] = i;            Hc[t].ch = i;            Hc[t].weight = a[i];            Hc[t].lchild = Hc[t].rchild = Hc[t].parents = 0;        }    }    b[++t] = '\0';    for(i = kinds + 1; i <= m; i++){        Hc[i].ch = '#';        Hc[i].lchild = Hc[i].rchild = Hc[i].parents = 0;    }    while(start <= m){        int min1 = INT_MAX,min2 = INT_MAX,min1num,min2num;        for(i = 1; i < start; i++){            if(!Hc[i].parents){                if(Hc[i].weight < min1){                    min2 = min1;                    min2num = min1num;                    min1 = Hc[i].weight;                    min1num = i;                }                else if(Hc[i].weight < min2)                {                    min2 = Hc[i].weight;                    min2num = i;                }            }        }        Hc[start].weight = Hc[min1num].weight + Hc[min2num].weight;        Hc[start].lchild = min2num;        Hc[start].rchild = min1num;        Hc[min1num].parents=Hc[min2num].parents=start;        start++;    }    Hccode = (Haffmancode)malloc((kinds+1) * sizeof(char *));    for(i = 1; i <= kinds; i++)    {        char *cd;        int p, c;        cd = (char *)malloc(kinds * sizeof(char));        start = kinds - 1;        cd[start]  = '\0';        c = i;        while(p = Hc[c].parents){            if(c == Hc[p].lchild) cd[--start] = '0';            else cd[--start] = '1';            c = p;        }        Hccode[i] = (char *)malloc((kinds - start) * sizeof(char));        strcpy(Hccode[i],&cd[start]);    }    return Hccode;}void replace(char *mingwen,char *secreat){    int i = 2 * kinds - 1, j = 0, start = 0, k = 0;    while(secreat[j] != '\0'){        if(secreat[j] == '1') i = Hc[i].rchild;        else i = Hc[i].lchild;        if(Hc[i].lchild == 0 && Hc[i].rchild == 0){            mingwen[k++] = Hc[i].ch;            i = 2 * kinds - 1;        }        j++;    }    if(i != 2 * kinds - 1)          mingwen[k++] = '#';    mingwen[k] = '\0';}void translate(char *secreat,char *mingwen){    int i, j, start = 0, k = 0;    while(mingwen[start] != '\0'){        for(i = 1; i <= kinds; i++){            if(b[i] != mingwen[start]) continue;            else{                for(j = 0; Hccode[i][j] != '\0'; j++){                    secreat[k++] = Hccode[i][j];                }                start++;                break;            }        }        if(i > kinds){            secreat[k++] = '#';            start++;        }    }    secreat[k] = '\0';}void minterface(){    clrscr();    printf("\t\t哈夫曼编码译码\n---------编码-----输入1\n---------译码-----输入2\n---------退出-----输入3\n");    printf("\t\tshow you command:");    int r;    scanf("%d",&r);    switch(r){       case 1: coding(); break;       case 2: decipher(); break;       case 3: return; break;       }}void coding(){    char txt[1000],code[10000],txt2[1000];    int r;    clrscr();    printf("请输入你想编码的文段(以'#'作为结束标志):\n");    deciph = 1;    Dataread(txt);    translate(code,txt);    printf("原文的哈夫曼编码为:");    puts(code);    printf("\n\t\t\t          返回----------输入0:\n\t\t\t继续编一下一段----------输入1:\n\t\t\t验证编码正确性----------输入3:");    printf("\n\t\tshow you command:");    scanf("%d",&r);    if(r==1) coding();    else if(r == 0) minterface();    else if(r == 3){        replace(txt2,code);        printf("破译上段密码如下:\n");        puts(txt2);        printf("\n\n\n\t\t\t------回主界面----------输入0:\n\t\t\t继续编一下一段----------输入1:");        printf("\n\t\tshow you command:");        scanf("%d",&r);        if(r) coding();        else minterface();        }}void decipher(){    char txt[1000],code[10000];    int r;    clrscr();    showthecode();    loop: printf("\n请输入你想破译的编码(以'#'作为结束标志):\n");    deciph = 0;    Dataread(code);    replace(txt,code);    printf("这段哈夫曼编码的原文为:");    puts(txt);    printf("\n\t\t\t          返回----------输入0:\n\t\t\t继续编一下一段----------输入1:\n\t\t\t    显示编码表----------输入2:");    printf("\n\t\tshow you command:");    scanf("%d",&r);    if(r){          if(r==2) showthecode();          goto loop;          }    else minterface();}void showthecode(){    int i;    printf("哈夫曼编码如下: \n");    for(i = 1; b[i] != '\0'; i++){        printf("%9s\t",Hccode[i]);        if(b[i] == '\n') printf("换行符\n");        else if(b[i] == ' ') printf("空格\n");        else printf("%c\n",b[i]);    }}int main(){    minterface();    return 0;}

0 0