鱼C论坛

 找回密码
 立即注册
查看: 2115|回复: 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
好了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DATA_SIZE        256
#define CODE_TABLE_SIZE        256

typedef struct noeud_tag
{
        char ch;
        size_t freq;
        struct noeud_tag *fils_g;        // 左枝点
        struct noeud_tag *fils_d;        // 右枝点
} noeud_t;

typedef struct
{
        char code[zxsq-anti-bbcode-100];
} code_item_t;

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

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

        //建立一个表格 现在频率全是0
        for(i = 0; i < 256; i++)
        {
                freq[zxsq-anti-bbcode-i] = 0;
        }

        // 计算字符串里每个字母的频率
        for(i = 0; i < length; i++)
        {
                car = chaine[zxsq-anti-bbcode-i];
                freq[zxsq-anti-bbcode-car]++;
        }

        return;
}

// 重写此函数
size_t init_noeud(noeud_t *data, int *freq)
{
        size_t index = 0;
        for(size_t i = 0; i < DATA_SIZE; ++i)
        {
                if(freq[zxsq-anti-bbcode-i] > 0)
                {
                        memset(&data[zxsq-anti-bbcode-index], 0, sizeof(data[zxsq-anti-bbcode-index]));
                        data[zxsq-anti-bbcode-index].ch = (char)i;
                        data[zxsq-anti-bbcode-index].freq = freq[zxsq-anti-bbcode-i];
                        ++index;
                }
        }

        return index;
}

// 按频率从小到大排序
void sort(noeud_t *data, size_t length)
{
        for(size_t i = 0; i < length; ++i)
        {
                for(size_t j = i + 1; j < length; ++j)
                {
                        if(data[zxsq-anti-bbcode-i].freq > data[zxsq-anti-bbcode-j].freq)
                        {
                                noeud_t tmp = data[zxsq-anti-bbcode-i];
                                data[zxsq-anti-bbcode-i] = data[zxsq-anti-bbcode-j];
                                data[zxsq-anti-bbcode-j] = tmp;
                        }
                }
        }
}

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

                data[--index] = data[zxsq-anti-bbcode-0];
                data[--index] = data[zxsq-anti-bbcode-1];

                memset(&data[zxsq-anti-bbcode-0], 0, sizeof(data[zxsq-anti-bbcode-0]));
                data[zxsq-anti-bbcode-0].fils_g = &data[index + 1];
                data[zxsq-anti-bbcode-0].fils_d = &data[zxsq-anti-bbcode-index];
                data[zxsq-anti-bbcode-0].freq = data[zxsq-anti-bbcode-0].fils_g->freq + data[zxsq-anti-bbcode-0].fils_d->freq;

                for(size_t i = 1; i < length - 1; ++i)
                        data[zxsq-anti-bbcode-i] = data[i + 1];
                --length;
        }
        return &data[zxsq-anti-bbcode-0];
}

void preorder_traversal(noeud_t *root)
{
        if(root)
        {
                printf("\nch:\t\'%c\'\n", root->ch);
                printf("pre:\t%u\n", root->freq);
                preorder_traversal(root->fils_g);
                preorder_traversal(root->fils_d);
        }
}

void traverse_tree(noeud_t *root, code_item_t *code_table, char code[zxsq-anti-bbcode-1024], size_t index)
{
        if(!root->fils_g && !root->fils_d)
        {
                code[zxsq-anti-bbcode-index] = '\0';
                strcpy(code_table[root->ch].code, code);
        }
        if(root->fils_g)
        {
                code[zxsq-anti-bbcode-index] = '0';
                traverse_tree(root->fils_g, code_table, code, index + 1);
        }
        if(root->fils_d)
        {
                code[zxsq-anti-bbcode-index] = '1';
                traverse_tree(root->fils_d, code_table, code, index + 1);
        }
}

void init_code_table(code_item_t *code_table, noeud_t *code_tree)
{
        char code[zxsq-anti-bbcode-1024];
        size_t index = 0;
        memset(code_table, 0, sizeof(code_item_t) * CODE_TABLE_SIZE);
        traverse_tree(code_tree, code_table, code, index);
}

// 尽量保证和原来一样,这里也使用数组
// 说真的,数组很不好用
// 为了和原来尽量一样,不得不用
int main(void)
{
        char *chaine = "aaababaaababbbbbbbbbbbbabcddddbcaaabbbbbbbbbbbabbaa";
        int freq[zxsq-anti-bbcode-256];
        size_t length;
        noeud_t data[zxsq-anti-bbcode-DATA_SIZE];
        noeud_t *code_tree;
        code_item_t code_table[zxsq-anti-bbcode-CODE_TABLE_SIZE];

        frequence(freq, chaine);
        length = init_noeud(data, freq);
        code_tree = huffman_tree(data, length);
        init_code_table(code_table, code_tree);

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

        preorder_traversal(code_tree);
        return(EXIT_SUCCESS);
}
a: 01
b: 1
c: 000
d: 001

ch:     ' '
pre:    51

ch:     ' '
pre:    21

ch:     ' '
pre:    6

ch:     'c'
pre:    2

ch:     'd'
pre:    4

ch:     'a'
pre:    15

ch:     'b'
pre:    30
请按任意键继续. . .

(, 下载次数: 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函数后,这个程序应该输出什么内容才是正确的
#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)       //这里弄不太懂  这个是结构体定义函数指针 还有输入的参数也是另一个结构体
{

}

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);
}
想知道小甲鱼最近在做啥?请访问 -> 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)

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

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

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

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

        return 0;
}

输出
0
1
2
3
4
5
6
7
8
9
请按任意键继续. . .


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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-17 08:59

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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