鱼C论坛

 找回密码
 立即注册
查看: 1908|回复: 36

[已解决]哈夫曼码结构体的疑问

[复制链接]
发表于 2019-2-17 00:29:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
问题出现在哈夫曼码那个函数里 当结构体定义函数指针时而且输入的参数也是另一个结构体 这里要怎么做?其他函数都能运行 就这里不会





#include <stdlib.h>
#include <stdio.h>
#include <string.h>


//
struct codage{                          //编码的结构体里有一个字母和一个字母出现的频率
    char symbole[100];
    int freq;
};

typedef struct codage codage;


//
struct noeud{                          //树的结构体有字符串,左枝点 右枝点 父枝点
    char symbole[100];
    struct noeud *fils_g;         //左枝点
    struct noeud *fils_d;         //右枝点
    struct noeud *pere;         //父枝点
};

typedef struct noeud noeud;


void frequence(int *freq,char *chaine)     //此函数是为了找出字符串里每个ASCII字符的频率
{
    char car;
    int i;
    int length;
   
    // 计算字符串的长度
    length=strlen(chaine);
   
    //建立一个表格 现在频率全是0
    for(i=0;i<256;i++)
    {
        freq[i]=0;
    }
   
    // 计算字符串里每个字母的频率
    for(i=0;i<length;i++)
    {
        car=chaine[i];
        freq[car]++;
    }
   
    return;
}


void  tri_bulle(codage *tab_codage, int length)      //排序函数
{
    int u;
    char s[100];
    int i,j;
   
    for(i=0;i<length;i++)
    {
        for(j=0;j<length-1;j++)
        {
            if( tab_codage[j].freq < tab_codage[j+1].freq )
            {
                // on permute tab_codage[j] et tab_codage[j+1]
                // symbole
                strcpy(s,tab_codage[j].symbole);
                strcpy(tab_codage[j].symbole,tab_codage[j+1].symbole);
                strcpy(tab_codage[j+1].symbole,s);
               
                //freq
                u=tab_codage[j].freq;
                tab_codage[j].freq=tab_codage[j+1].freq;
                tab_codage[j+1].freq=u;
            }
        }
    }
    return;
}


int init_tab_codage(codage *tab_codage,int *freq)   //使用频率>0的字母填入表格里并且以降序排序
{
    int nb=0,i,j,length;
   
    //我们在tab_codage这个列表中插入每个频率大于0的字符
   
    j=0;
    for(i=0;i<256;i++)
    {
        if(freq[i] > 0)
        {
            tab_codage[j].freq=freq[i];
            tab_codage[j].symbole[0]=(char)i;
            tab_codage[j].symbole[1]='\0';
            j++;
        }
    }
   
    length=j;
    // on affiche le contenu de tab_codage
    for(i=0;i<length;i++)
    {
        printf("caractère \"%s\", freq=%d\n",tab_codage[i].symbole,tab_codage[i].freq);
    }
   
    // 进行表格排序
    tri_bulle(tab_codage, length);
   
    // 显示已经排好序的表格
    for(i=0;i<length;i++)
    {
        printf("caractère \"%s\", freq=%d\n",tab_codage[i].symbole,tab_codage[i].freq);
    }
   
    return(length);
}



noeud *trouve_noeud(noeud *racine,char *symbole)   //这个函数, 用于搜索包含符号树的叶
{
    noeud *t;
    t=racine;
    int compteur=0;
   
    while( (t != NULL) )
    {
        
        if( strcmp(t->symbole,symbole) == 0)
        {
            return(t);
        }
        else if( (t->fils_g != NULL ) && ( strstr((t->fils_g)->symbole,symbole) != NULL) )
        {
            
            t=t->fils_g;
        }
        else if( (t->fils_d != NULL ) && ( strstr((t->fils_d)->symbole,symbole) != NULL) )
        {
            
            t=t->fils_d;
        }
        else
            return(NULL);
    }
   
}



noeud *huffman_code(codage *source,  int N)       //这里弄不太懂  这个是结构体定义函数指针 还有输入的参数也是另一个结构体
{
   
    codage *t;
    t=source;
    int i;
    int a[10];
    if (t[i].symbole !=NULL)
    {
        if(t[i].fils_g==NULL&&t[i].fils_d==NULL)
        {
            int i;
            
            for(i=0;i<N;i++)
                printf("%s",t[i]);
            printf("\n");
        }
        else
        {
            a[N]=0;
            huffman_code(t[i].fils_g,N+1);
            a[N]=1;
            huffman_code(t[i].fils_d,N+1);
        }
    }
   
}

int main()
{
   
   
    char *chaine="aaababaaababbbbbbbbbbbbabcddddbcaaabbbbbbbbbbbabbaa";
   
    int freq[256];
    codage source[256];
    int length;
    noeud *racine;
   
    frequence(freq,chaine);
    length=init_tab_codage(source,freq);
    racine=huffman_code(source,length);
   
    return(EXIT_SUCCESS);
}
最佳答案
2019-2-20 16:51:12
好了

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. #define DATA_SIZE        256
  5. #define CODE_TABLE_SIZE        256

  6. typedef struct noeud_tag
  7. {
  8.         char ch;
  9.         size_t freq;
  10.         struct noeud_tag *fils_g;        // 左枝点
  11.         struct noeud_tag *fils_d;        // 右枝点
  12. } noeud_t;

  13. typedef struct
  14. {
  15.         char code[100];
  16. } code_item_t;

  17. // 能不改的函数尽量不改
  18. void frequence(int *freq, char *chaine)                // 此函数是为了找出字符串里每个ASCII字符的频率
  19. {
  20.         char car;
  21.         int i;
  22.         int length;

  23.         // 计算字符串的长度
  24.         length = strlen(chaine);

  25.         //建立一个表格 现在频率全是0
  26.         for(i = 0; i < 256; i++)
  27.         {
  28.                 freq[i] = 0;
  29.         }

  30.         // 计算字符串里每个字母的频率
  31.         for(i = 0; i < length; i++)
  32.         {
  33.                 car = chaine[i];
  34.                 freq[car]++;
  35.         }

  36.         return;
  37. }

  38. // 重写此函数
  39. size_t init_noeud(noeud_t *data, int *freq)
  40. {
  41.         size_t index = 0;
  42.         for(size_t i = 0; i < DATA_SIZE; ++i)
  43.         {
  44.                 if(freq[i] > 0)
  45.                 {
  46.                         memset(&data[index], 0, sizeof(data[index]));
  47.                         data[index].ch = (char)i;
  48.                         data[index].freq = freq[i];
  49.                         ++index;
  50.                 }
  51.         }

  52.         return index;
  53. }

  54. // 按频率从小到大排序
  55. void sort(noeud_t *data, size_t length)
  56. {
  57.         for(size_t i = 0; i < length; ++i)
  58.         {
  59.                 for(size_t j = i + 1; j < length; ++j)
  60.                 {
  61.                         if(data[i].freq > data[j].freq)
  62.                         {
  63.                                 noeud_t tmp = data[i];
  64.                                 data[i] = data[j];
  65.                                 data[j] = tmp;
  66.                         }
  67.                 }
  68.         }
  69. }

  70. noeud_t *huffman_tree(noeud_t *data, size_t length)
  71. {
  72.         size_t index = DATA_SIZE;        // 指向最后一个可用位置
  73.         while(length != 1)
  74.         {
  75.                 sort(data, length);

  76.                 data[--index] = data[0];
  77.                 data[--index] = data[1];

  78.                 memset(&data[0], 0, sizeof(data[0]));
  79.                 data[0].fils_g = &data[index + 1];
  80.                 data[0].fils_d = &data[index];
  81.                 data[0].freq = data[0].fils_g->freq + data[0].fils_d->freq;

  82.                 for(size_t i = 1; i < length - 1; ++i)
  83.                         data[i] = data[i + 1];
  84.                 --length;
  85.         }
  86.         return &data[0];
  87. }

  88. void preorder_traversal(noeud_t *root)
  89. {
  90.         if(root)
  91.         {
  92.                 printf("\nch:\t\'%c\'\n", root->ch);
  93.                 printf("pre:\t%u\n", root->freq);
  94.                 preorder_traversal(root->fils_g);
  95.                 preorder_traversal(root->fils_d);
  96.         }
  97. }

  98. void traverse_tree(noeud_t *root, code_item_t *code_table, char code[1024], size_t index)
  99. {
  100.         if(!root->fils_g && !root->fils_d)
  101.         {
  102.                 code[index] = '\0';
  103.                 strcpy(code_table[root->ch].code, code);
  104.         }
  105.         if(root->fils_g)
  106.         {
  107.                 code[index] = '0';
  108.                 traverse_tree(root->fils_g, code_table, code, index + 1);
  109.         }
  110.         if(root->fils_d)
  111.         {
  112.                 code[index] = '1';
  113.                 traverse_tree(root->fils_d, code_table, code, index + 1);
  114.         }
  115. }

  116. void init_code_table(code_item_t *code_table, noeud_t *code_tree)
  117. {
  118.         char code[1024];
  119.         size_t index = 0;
  120.         memset(code_table, 0, sizeof(code_item_t) * CODE_TABLE_SIZE);
  121.         traverse_tree(code_tree, code_table, code, index);
  122. }

  123. // 尽量保证和原来一样,这里也使用数组
  124. // 说真的,数组很不好用
  125. // 为了和原来尽量一样,不得不用
  126. int main(void)
  127. {
  128.         char *chaine = "aaababaaababbbbbbbbbbbbabcddddbcaaabbbbbbbbbbbabbaa";
  129.         int freq[256];
  130.         size_t length;
  131.         noeud_t data[DATA_SIZE];
  132.         noeud_t *code_tree;
  133.         code_item_t code_table[CODE_TABLE_SIZE];

  134.         frequence(freq, chaine);
  135.         length = init_noeud(data, freq);
  136.         code_tree = huffman_tree(data, length);
  137.         init_code_table(code_table, code_tree);

  138.         printf("a: %s\n", code_table['a'].code);
  139.         printf("b: %s\n", code_table['b'].code);
  140.         printf("c: %s\n", code_table['c'].code);
  141.         printf("d: %s\n", code_table['d'].code);

  142.         preorder_traversal(code_tree);
  143.         return(EXIT_SUCCESS);
  144. }
复制代码

  1. a: 01
  2. b: 1
  3. c: 000
  4. d: 001

  5. ch:     ' '
  6. pre:    51

  7. ch:     ' '
  8. pre:    21

  9. ch:     ' '
  10. pre:    6

  11. ch:     'c'
  12. pre:    2

  13. ch:     'd'
  14. pre:    4

  15. ch:     'a'
  16. pre:    15

  17. ch:     'b'
  18. pre:    30
  19. 请按任意键继续. . .
复制代码


(, 下载次数: 0)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2019-2-17 02:17:53 | 显示全部楼层
求大神解疑
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-17 11:05:36 From FishC Mobile | 显示全部楼层
那个是指针函数吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-17 11:12:13 From FishC Mobile | 显示全部楼层
改成void类型,试试
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-17 15:39:27 | 显示全部楼层
lovefishc.com 发表于 2019-2-17 04:12
改成void类型,试试

是啊  书上的题要求用指针函数 不能用void
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-18 16:14:24 | 显示全部楼层
有没有大佬帮帮忙啊?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-18 21:40:58 From FishC Mobile | 显示全部楼层
qpwoeiruyt 发表于 2019-2-17 15:39
是啊  书上的题要求用指针函数 不能用void

那返回地址不就行了吗。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-18 21:42:37 From FishC Mobile | 显示全部楼层
这个写的是哈夫曼编码,最后打印出来?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-18 21:43:31 From FishC Mobile | 显示全部楼层
这个是题的答案吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-18 21:45:49 From FishC Mobile | 显示全部楼层
qpwoeiruyt 发表于 2019-2-18 16:14
有没有大佬帮帮忙啊?

在函数最后加上
return t;
试一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-18 22:08:18 From FishC Mobile | 显示全部楼层
这个函数用的是递归,是这里不懂吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-19 00:41:09 | 显示全部楼层
lovefishc.com 发表于 2019-2-18 14:42
这个写的是哈夫曼编码,最后打印出来?

对 这个要打印哈夫曼码  这个不是答案  老师说只需要更改noeud *huffman_code(codage *source,  int N)  这个函数里面的东西让它运行起来 其他函数不须改变都可运行,上面huffman_code 里是我写的 但是应该错了 我不太懂指针函数这方面 求大神改改我的huffman—code那里 使最后能打印出哈夫曼码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-19 15:04:53 | 显示全部楼层
这个怕不是很好改,错误很多啊。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-19 15:19:40 | 显示全部楼层
mqcake 发表于 2019-2-19 08:04
这个怕不是很好改,错误很多啊。

就是把我的noeud *huffman_code(codage *source,  int N)  里面的东西改了就好 其他都OK的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-19 21:50:41 | 显示全部楼层
求大神帮帮忙
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-19 22:31:22 | 显示全部楼层

1.如果可以,你需要再补充一些问题,我总感觉哪里没有弄明白
2.这个程序要输出什么内容才是正确的?

最重要的是第2点,我需要第2点来反向理解第1点,如果你能补充一些的话会更好
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-20 00:25:29 | 显示全部楼层
人造人 发表于 2019-2-19 15:31
1.如果可以,你需要再补充一些问题,我总感觉哪里没有弄明白
2.这个程序要输出什么内容才是正确的?

就是输出哈夫曼码    比如输入aaacccbbb 这个字符串然后打印出各个字母的哈夫曼码  a=001 b=01 这样子
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-20 00:34:29 | 显示全部楼层
qpwoeiruyt 发表于 2019-2-20 00:25
就是输出哈夫曼码    比如输入aaacccbbb 这个字符串然后打印出各个字母的哈夫曼码  a=001 b=01 这样子

首先,你先确认一下这个代码
也就是说现在这个代码就差huffman_code函数了,其他部分都没问题,是这样吧
然后,完成了huffman_code函数后,这个程序应该输出什么内容才是正确的
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>


  4. //
  5. struct codage{                          //编码的结构体里有一个字母和一个字母出现的频率
  6.         char symbole[100];
  7.         int freq;
  8. };

  9. typedef struct codage codage;


  10. //
  11. struct noeud{                          //树的结构体有字符串,左枝点 右枝点 父枝点
  12.         char symbole[100];
  13.         struct noeud *fils_g;         //左枝点
  14.         struct noeud *fils_d;         //右枝点
  15.         struct noeud *pere;         //父枝点
  16. };

  17. typedef struct noeud noeud;


  18. void frequence(int *freq, char *chaine)     //此函数是为了找出字符串里每个ASCII字符的频率
  19. {
  20.         char car;
  21.         int i;
  22.         int length;

  23.         // 计算字符串的长度
  24.         length = strlen(chaine);

  25.         //建立一个表格 现在频率全是0
  26.         for(i = 0; i < 256; i++)
  27.         {
  28.                 freq[i] = 0;
  29.         }

  30.         // 计算字符串里每个字母的频率
  31.         for(i = 0; i < length; i++)
  32.         {
  33.                 car = chaine[i];
  34.                 freq[car]++;
  35.         }

  36.         return;
  37. }


  38. void  tri_bulle(codage *tab_codage, int length)      //排序函数
  39. {
  40.         int u;
  41.         char s[100];
  42.         int i, j;

  43.         for(i = 0; i < length; i++)
  44.         {
  45.                 for(j = 0; j < length - 1; j++)
  46.                 {
  47.                         if(tab_codage[j].freq < tab_codage[j + 1].freq)
  48.                         {
  49.                             // on permute tab_codage[j] et tab_codage[j+1]
  50.                             // symbole
  51.                                 strcpy(s, tab_codage[j].symbole);
  52.                                 strcpy(tab_codage[j].symbole, tab_codage[j + 1].symbole);
  53.                                 strcpy(tab_codage[j + 1].symbole, s);

  54.                                 //freq
  55.                                 u = tab_codage[j].freq;
  56.                                 tab_codage[j].freq = tab_codage[j + 1].freq;
  57.                                 tab_codage[j + 1].freq = u;
  58.                         }
  59.                 }
  60.         }
  61.         return;
  62. }


  63. int init_tab_codage(codage *tab_codage, int *freq)   //使用频率>0的字母填入表格里并且以降序排序
  64. {
  65.         int nb = 0, i, j, length;

  66.         //我们在tab_codage这个列表中插入每个频率大于0的字符

  67.         j = 0;
  68.         for(i = 0; i < 256; i++)
  69.         {
  70.                 if(freq[i] > 0)
  71.                 {
  72.                         tab_codage[j].freq = freq[i];
  73.                         tab_codage[j].symbole[0] = (char)i;
  74.                         tab_codage[j].symbole[1] = '\0';
  75.                         j++;
  76.                 }
  77.         }

  78.         length = j;
  79.         // on affiche le contenu de tab_codage
  80.         for(i = 0; i < length; i++)
  81.         {
  82.                 printf("caractère "%s", freq=%d\n", tab_codage[i].symbole, tab_codage[i].freq);
  83.         }

  84.         // 进行表格排序
  85.         tri_bulle(tab_codage, length);

  86.         // 显示已经排好序的表格
  87.         for(i = 0; i < length; i++)
  88.         {
  89.                 printf("caractère "%s", freq=%d\n", tab_codage[i].symbole, tab_codage[i].freq);
  90.         }

  91.         return(length);
  92. }



  93. noeud *trouve_noeud(noeud *racine, char *symbole)   //这个函数, 用于搜索包含符号树的叶
  94. {
  95.         noeud *t;
  96.         t = racine;
  97.         int compteur = 0;

  98.         while((t != NULL))
  99.         {

  100.                 if(strcmp(t->symbole, symbole) == 0)
  101.                 {
  102.                         return(t);
  103.                 }
  104.                 else if((t->fils_g != NULL) && (strstr((t->fils_g)->symbole, symbole) != NULL))
  105.                 {

  106.                         t = t->fils_g;
  107.                 }
  108.                 else if((t->fils_d != NULL) && (strstr((t->fils_d)->symbole, symbole) != NULL))
  109.                 {

  110.                         t = t->fils_d;
  111.                 }
  112.                 else
  113.                         return(NULL);
  114.         }

  115. }



  116. noeud *huffman_code(codage *source, int N)       //这里弄不太懂  这个是结构体定义函数指针 还有输入的参数也是另一个结构体
  117. {

  118. }

  119. int main()
  120. {


  121.         char *chaine = "aaababaaababbbbbbbbbbbbabcddddbcaaabbbbbbbbbbbabbaa";

  122.         int freq[256];
  123.         codage source[256];
  124.         int length;
  125.         noeud *racine;

  126.         frequence(freq, chaine);
  127.         length = init_tab_codage(source, freq);
  128.         racine = huffman_code(source, length);

  129.         return(EXIT_SUCCESS);
  130. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-20 01:04:18 | 显示全部楼层
人造人 发表于 2019-2-19 17:34
首先,你先确认一下这个代码
也就是说现在这个代码就差huffman_code函数了,其他部分都没问题,是这样吧 ...

是的 其他都是正确的 就差noeud *huffman_code(codage *source, int N)

最后完成后是能打印出哈夫曼码出来  例如a=001 这样
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-20 01:19:29 | 显示全部楼层
qpwoeiruyt 发表于 2019-2-20 01:04
是的 其他都是正确的 就差noeud *huffman_code(codage *source, int N)

最后完成后是能打印出哈夫曼码 ...

我还是没有问到我需要的内容,我举个例子

下面这个程序
  1. #include <stdio.h>

  2. int main(void)
  3. {
  4.         for(int i = 0; i < 10; ++i)
  5.                 printf("%d\n", i);

  6.         return 0;
  7. }
复制代码


输出
  1. 0
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9
  11. 请按任意键继续. . .
复制代码



对于你的这个程序,如果完成了huffman_code函数,输出是什么样的?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 07:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表