标题:求大神看看这个程序吧,这是一个赫夫曼编码题,将根据输入字母个数的多少作 ...
取消只看楼主
zheng2015
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-5-31
结帖率:0
已结贴  问题点数:20 回复次数:4 
求大神看看这个程序吧,这是一个赫夫曼编码题,将根据输入字母个数的多少作为权值将字母进行编码,当输入的字母个数很多时程序在for循环里面就出错了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define M 200



typedef struct {
    char c;
    int count;
    int parent,lchild,rchild;
    char Hcode[6];
}HTNode, *HuffmanTree;
typedef char * * HuffmanCode;
HTNode L[26];

const int N=sizeof(HTNode);
HuffmanTree HT=NULL;
HuffmanCode HC=NULL;

void main() {
    int CountLetter(char str[]);
    void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n);
    void Coding(char str[],char *p);
    void Translate(char code[], char *p,int n);
   
    FILE *fp;

    int i,n;//n为短文中出现的不同英文字母的个数
    char str1[M],str2[M],str3[M];
    char code1[26*M]="\0",code2[26*M]="\0";//此处必须让code初始化‘\0’,否则会出现错误。
    for(i=0; i<26; i++)
        L[i].count=0;
    printf("Please input centenses : \n");
    gets(str1);
   

    if((fp=fopen("a","w"))==NULL) {
        printf("can't open file\n");
        exit(0);
    }//用只写入的方式打开“a”文件
    fputs(str1,fp);//向文件“a”中写入该短文
    fclose(fp);//打开文件后要将其关闭,否则会出现泄露

    if((fp=fopen("a","r"))==NULL) {
        printf("Error!\n");
        exit(0);
    }//用只读的方式打开文件“a”
    fgets(str2,M,fp);//从fp指向的文件中读取字符串并将其放入字符串str中
    fclose(fp);
    //puts(str2);
    n=CountLetter(str2);   
   
    HuffmanCoding(HT, HC, n);

    Coding(str2,code1);
    if((fp=fopen("b","w"))==NULL) {
        printf("can't open file\n");
        exit(0);
    }//打开文件b并向其写入已编码的短文
    fputs(code1,fp);
    fclose(fp);

    if((fp=fopen("b","r"))==NULL) {
        printf("ERROR!\n");
        exit(0);
    }
    fgets(code2,26*M,fp);
    fclose(fp);
//    puts(code2);
//    Translate(code2,str3,n);
//    puts(str3);
}

int CountLetter(char str[]) {
    int i=0,j,flag;//如果数组L中出现了要查找的字母,则flag=1,否则flag=0
    for(i=0; str[i]!='\0'; i++) {//检查str[i]是否已在数组L中出现,若出现则将其出现次数加一,若没有出现将其放入L中并让其出现次数加一
        flag=0;
        if(str[i]!=' ' && str[i]!=',') {
            for(j=0; flag==0 && L[j].count!=0; j++) {
                if(L[j].c==str[i] || L[j].c==str[i]+32) {
                    L[j].count++;
                    flag=1;
                }
            }
            if(flag==0) {
                if(str[i]>64 && str[i]<91)
                    L[j].c=str[i]+32;
                else
                    L[j].c=str[i];
                L[j].count++;
            }
        }
    }
    for(i=0; L[i].count!=0 ;i++)
        printf("%c  %d\n",L[i].c,L[i].count);
    printf("总的出现字母的个数为%d\n",i);
    return i;
}


void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n) {//构建赫夫曼树HT,并求出n个字符的赫夫曼编码
    int i,j,k,m,start,c,f;//m为赫夫曼树总的结点个数,start是编码个数,c为结点,f为c的父亲
    int min;//min为最小权值
    int s1,s2;//s1为权值最小结点在HT中的存储位置,s2为权值次小结点在HT中的位置
    char *cd;
    HuffmanTree p;

    if(n<=1) return ;
    m=2*n-1;

    HT=(HuffmanTree) malloc((m+1) * sizeof(HTNode));

    for(i=1; i<=n; ++i) {//切记p的值变化
        HT[i*N].c=L[i-1].c;
        HT[i*N].count=L[i-1].count;
        HT[i*N].parent=0;
        HT[i*N].lchild=0;
        HT[i*N].rchild=0;
    //    p=HT+i*N;
    //    p->c=L[i-1].c;
    //    p->count=L[i-1].count;
    //    p->parent=0;
    //    p->lchild=0;
    //    p->rchild=0;
    //    p->Hcode;
    }
   
    for(; i<=m; ++i) {
//        printf("p.");
//        p=HT+i*N;
//        p->c=' ';
//        p->count=0;
//        p->lchild=0;
//        p->parent=0;
//        p->rchild=0;
        HT[i*N].c=' ';
        HT[i*N].count=0;
        HT[i*N].parent=0;
        HT[i*N].lchild=0;
        HT[i*N].rchild=0;
    }
    printf("wwwwwww");

    for(i=n+1; i<=m; ++i) {//建赫夫曼树
    //Select(HT,i-1,s1,s2);
        for(k=1; HT[k*N].parent!=0 && k<=i-1; k++) ;
        min=HT[k*N].count;
        s1=k;
        for(j=1; j<i; j++) {
            if(HT[j*N].count < min && HT[j*N].parent==0) {
                min=HT[j*N].count;
                s1=j;
            }
        }   
   
        for(k=1; HT[k*N].parent!=0 || k==s1; k++) ;
        min=HT[k*N].count;
        s2=k;
        for(j=1; j<i; j++) {
            if(HT[j*N].count < min && HT[j*N].parent==0 && j!=s1) {
                min=HT[j*N].count;
                s2=j;
            }
        }//目的找到HT中权值较小的两个结点
        HT[s1*N].parent=i;
        HT[s2*N].parent=i;
        HT[i*N].lchild=s1;
        HT[i*N].rchild=s2;
        HT[i*N].count=HT[s1*N].count+HT[s2*N].count;
    }
   
    //从叶子到根逆向求每个字符的赫夫曼编码
    //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*N].parent; f!=0; c=f, f=HT[f*N].parent) {
            if(HT[f*N].lchild==c)
                cd[--start]='0';
            else
                cd[--start]='1';
        }
        strcpy(L[i-1].Hcode,&cd[start]);
    }
   
    for(i=1; i<=n; i++)
        printf("%c  %s\n",L[i-1].c,L[i-1].Hcode);

    free (cd);
}

void Coding(char str[],char *p) {
    int i,j;

    for(i=0; str[i]!='\0'; i++) {
        if(str[i]==' ')
            strcat(p," ");
        if(str[i]==',')
            strcat(p,",");
        if(str[i]!=' ' && str[i]!=',') {
            for(j=1; str[i]!=L[j-1].c && str[i]!=L[j-1].c-32; j++) ;
            strcat(p,L[j-1].Hcode);//将每个字母的编码连接在一起
        }
   
    }
    printf("%s",p);
}
搜索更多相关主题的帖子: include parent count 字母 
2015-05-31 00:24
zheng2015
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-5-31
得分:0 
回复 2楼 林月儿
可是亲,我选择的是用顺序结构存取二叉树,所以结点的定义没有问题,
我一步一步执行的时候,发现是在
for(; i<=m; ++i) {
    HT[i*N].c=' ';
    HT[i*N].count=0;
    HT[i*N].parent=0;
    HT[i*N].lchild=0;
    HT[i*N].rchild=0;
//    HT[i*N].Hcode={'\0'};
}
该循环处出现问题,循环到一定位置就不进行了,,,,,
2015-05-31 10:16
zheng2015
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-5-31
得分:0 
回复 4楼 林月儿


不知道你明白了没
2015-05-31 18:38
zheng2015
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-5-31
得分:0 
回复 6楼 林月儿
最开始我写的代码就是你给我修改的,但最后我意识到不应该是这样。
typedef struct {
    char c;
    int count;
    int parent,lchild,rchild;
    char Hcode[6];
}HTNode,*HuffmanTree;
故用HuffmanTree定义的变量都是一个指针。
HuffmanTree H,所以H是一个指向HTNode类型的指针。
H[i]相当于(H+i)这个地址单元的内容,
每个结点的大小是N=sizeof(HTNode),如果想表示某个结点则需要H[i*N]
2015-06-01 17:49
zheng2015
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-5-31
得分:0 
回复 6楼 林月儿
其实,亲,我想解决的是这样一个问题。
为什么当我输入字母个数较少时程序能正常运行,而且结果也正确,但当我输入的字母个数较多时它就不能出来想要的结果,待我慢慢检查时发现它是在一个for循环里面出不来了,请问为什么会这样呢?
下面是我程序执行演示:

2015-06-01 18:00



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-446014-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.113230 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved