为了账号安全,请及时绑定邮箱和手机立即绑定

求大大指教,,,写了个C语言数据结构的哈夫曼编码,可是哪里出错了,,,???

求大大指教,,,写了个C语言数据结构的哈夫曼编码,可是哪里出错了,,,???

lukuang 2016-06-06 10:51:52
/* 哈夫曼编码 */ #include<stdio.h> #include<stdlib.h>  #include<string.h> #include<ctype.h> #define MAX    100 /*哈夫曼树结点结构定义 */ typedef struct {  int weight;  //存放字符ch的权值   char ch;     //记录字符   int lchild, rchild, parent;//存储左孩子、右孩子以及父结点  } TNode, *PHT; /* 哈夫曼编码表的元素结构定义  */ typedef struct {    char ch;       // 编码对应的字符    char *pcode;   // 指向编码字符串的指针 } TCode, *PCode; /*   *统计字符串text中字符出现的频率,参数n为字符串长度  *返回值:text中出现的不同种类的字符个数  *副作用:通过指针参数间接返回两个数组:  *  1)dict:字符数组,存放 text中出现的不同种类的字符  *  2)freq:整型数组,存放 text中出现的不同种类的字符的出现频率   */ int calc_freq(char text[], int **freq, char **dict, int n){  int i,j, k, nchar = 0;  int *pwght;  char *pch;  int tokens[256] = {0};  //根据输入的文本字符串逐一统计字符出现的频率   for(i = 0; i < n; ++i){   tokens[text[i]]++;  }    //统计共有多少个相异的字符出现在文本串中   for(i = 0; i < 256; i++){   if( tokens[i] > 0 ){    nchar++;   }  }  //为权重数组分配空间   pwght=(int*)malloc(sizeof(int)*nchar);  if(!pwght){   printf("为权重数组分配空间失败!\n");   exit(0);  }    //为字符数组(字典)分配空间   pch=(char *)malloc(sizeof(char)*nchar);  if( !pch ){   printf("为字符数组(字典)分配空间失败!\n");   exit(0);  }    k = 0;  for(i = 0; i < 256; ++i){   if( tokens[i] > 0 ){    pwght[k] = tokens[i];    pch[k] = (char)i;  //强制类型转换     k++;   }  }    *freq = pwght;  *dict = pch;  for(i=0;i<nchar;i++)     printf("%c\t%d\n",pch[i],pwght[i]);    return nchar; } /*构建哈夫曼树 */ PHT create_htree( int **freq, int n ){  PHT pht;   int i, lc, rc, ntotal = 0;  ntotal = (2 * n) - 1; // Huffman树的结点总数    pht = (PHT) malloc( sizeof( TNode ) * ntotal );  for( i = 0; i < ntotal; ++i ){ // Huffman树结点初始化   pht[i].weight = (i < n) ? *freq[i] : 0;   pht[i].lchild = -1;    pht[i].rchild = -1;    pht[i].parent = -1;  }  for( i = n; i < ntotal; ++i ){ // 构建Huffman树   select_subtree( pht, (i-1), &lc, &rc );   pht[lc].parent = i;    pht[rc].parent = i;   pht[i].lchild = lc;    pht[i].rchild = rc;   pht[i].weight = pht[lc].weight + pht[rc].weight;  }  printf("创建哈夫曼树成功!\n");  return pht; } /*子树选择算法 */ int select_subtree(PHT pht, int n, int *pa, int *pb){//n为哈夫曼树结点数目   int id, ida = -1, idb= -1;              // ida存放权重最小的结点下标  int wa = INT_MAX, wb = INT_MAX;         // wa最小值 wb次小值  for(id = 0; id <= n; id++){   if(pht[id].parent == -1){    if( pht[id].weight < wa ){     idb = ida;                  // 重置次小值结点下标      wb = wa;                    //将较大的权值复制给wb      ida = id;                   //重置最小值结点下标      wa = pht[id].weight;        //将最小的权值记录为wa      }    else if(pht[id].weight < wb ){  //新权值大于wa小于wb         idb = id;                   //重置次小值结点下标      wb = pht[id].weight;        //重置次小值      }   }  }  *pa = ida;   *pb = idb;   return 0; } /* 根据哈夫曼树pht求哈夫曼编码表book */ void htree_encoding (PHT pht, TCode *book, int n){  int i, c, p, start; // start表示编码在cd中的起始位置  char cd[n+1];   cd[n]='\0'; // 临时存放编码  for(i = 0; i < n; i++){ // 依次求叶子pht[i]的编码   book[i].ch = pht[i].ch; // 读入叶结点pht[i]对应的字符   start = n;    c = i; // 从叶结点pht[i]开始上溯   while( p = pht[c].parent > 0){    if(pht[p].lchild == c)        cd[--start]='0';     else        cd[--start] ='1';     c = p;    } // 继续上溯直到根节点   strcpy(book[i].pcode, &cd[start]); // 复制编码位串     }       printf("哈夫曼编码成功!\n"); } void print_htreecode(TCode *book,int n){  int i;  for(i=0;i<n;i++){   printf("%c\t%d\n",book[i].ch,book[i].pcode);  }  printf("哈夫曼编码打印成功!\n"); }   void main(){     char text[MAX];     int scount=0,nchar=0,n;     int weights[MAX];     int **freq;     char **dict;     PHT pht;     TCode *book;          //从键盘输入英文字符串      printf("请输入英文字符串:\n");     while((text[scount]=getchar())!='\n')         scount++;               //统计字符串中不同字符出现的频率并打印相应信息         calc_freq(text,freq,dict,scount);          // 构建哈夫曼树     create_htree(freq,nchar);        //遍历哈夫曼树生成哈夫曼编码  htree_encoding (pht,book,nchar);    printf("打印每个字符的哈夫曼编码如下:\n");  printf("字符\t编码\n");  print_htreecode(book,nchar);      }
查看完整描述

1 回答

?
不偏不易

TA贡献96条经验 获得超118个赞

好怀念,当年我也是能自己写出这些各种树,各种遍历的人啊。现在已经废了。。

如何查错。DEBUG,设置断点并一步步走。

能正常启动并运行的,只是输出有问题,或者运行过程中出错的,可以选择在每一次输出的语句设置断点。然后每一步输出后,观察变量值是否正确。

如果不能启动,直接爆炸的,请先不要在主函数中调用所有的函数,可以先把大部分注释掉,然后一个个测试。其实这一部分应该在编写过程中做,写完一部分就测试一部分。

这些都能做到,以后大部分问题,都可以自己解决。

查看完整回答
反对 回复 2016-06-07
  • 1 回答
  • 0 关注
  • 1721 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信