注册 登录
编程论坛 数据结构与算法

Huffman树的建立

Karryu 发布于 2016-10-29 21:32, 2453 次点击
程序代码:
#include <stdio.h>
#include <malloc.h>
#define N 10
#define n 5

int i;

struct node
{
    char leaves;
    int weight;
    int lch;
    int rch;
    int parent;
}

creat()
{    struct node tree[N];
    int j;
    int MAX=1000;
    int min1,min2,min11,min22;
    for(i=0;i<(2*n-1);i++)
    {
        tree[i].parent=-1;
        tree[i].lch=-1;
        tree[i].rch=-1;
        printf("%d",i);
    }
    printf("%d",i);
    for(i=0;i<n;i++)
    {
        printf("请输入叶结点及权值:");
        scanf("%c %d",&tree[i].leaves,&tree[i].weight);
        
    }
    for(i=n;i<2*n-1;i++)                       //n个叶节点进行n-1次合并
    {
        min1=min2=MAX;
        min11=min22=0;
        for(j=0;j<n;j++)
        {
            if(tree[j].parent==-1)            //检查未合并的结点
            {
                if(tree[j].weight<min1)
                {
                    min22=min11;
                    min11=j;
                    min2=min1;
                    min1=tree[j].weight;
                }
                else
                    if(tree[j].weight<min2)
                    {
                        min22=j;
                        min2=tree[j].weight;
                    }
            }
        }
        tree[min11].parent=i;             //当前合并结点1的父结点为新节点
        tree[min22].parent=i;             //当前合并结点2的父结点为新节点
        tree[i].weight=tree[min11].weight+tree[min22].weight;  //新结点的权值
        tree[i].lch=min11;
        tree[i].rch=min22;
        continue;
    }
    tree[2*n-2].parent=-1;               //令最后一个结点的parent为-1
}
main()
{
    struct node tree[N];
    int j,k,t,pr,s;
    int code[n][n];
    creat();
    for(i=0;i<n;i++)
    {
        t=i;                        //t记录当前结点位置
        k=n-2;                      //j表示当前结点所在层次
        while(tree[t].parent!=-1)   //当前结点不是根结点时
        {
            pr=tree[t].parent;
            if(t==tree[pr].lch) code[i][k]=0;       //左子树记为0
            else code[i][k]=1;                      //右子树记为1
            k=k-1;
            t=pr;
        }
        code[i][n-1]=k+1;          //记录编码起始位置
    }
    printf("\nhuffman编码为:");
    for(i=0;i<n;i++)
    {
        s=code[i][n-1];
        for(;s<n-1;s++)
        {
            printf("%c",tree[i].leaves);
            printf("%d",code[i][s]);
        }
        printf("\n");
    }
}


请问这个建立huffman树的程序是哪里出错了
在输入结点时那个循环也不正常 会出现
只有本站会员才能查看附件,请 登录

这样的情况
然后下面运行出错
3 回复
#2
书生牛犊2016-10-29 23:53
只有本站会员才能查看附件,请 登录

程序代码:
#include <stdio.h>
#include <malloc.h>
#define N 10
#define n 5

int i;

struct node{
    char leaves;
    int weight;
    int lch;
    int rch;
    int parent;
};

void creat()
{    struct node tree[N];
    int j;
    int MAX=1000;
    int min1,min2,min11,min22;
    for(i=0;i<(2*n-1);i++)
    {
        tree[i].parent=-1;
        tree[i].lch=-1;
        tree[i].rch=-1;
        printf("%d",i);
    }
    printf("%d",i);
    for(i=0;i<n;i++)
    {        

        printf("请输入叶结点及权值:");
        scanf("%c %d",&tree[i].leaves,&tree[i].weight);//诚如你所见问题出在这里,原因在于第二次的%c读到了一个回车换行符,导致整个scanf都跟着乱了

        getchar();//可行的解决方案之一。。用这个getchar读走缓存中的那个空白符

        printf("{%c,%d}",tree[i].leaves,tree[i].weight);
    }
    for(i=n;i<2*n-1;i++)                       //n个叶节点进行n-1次合并
    {
        min1=min2=MAX;
        min11=min22=0;
        for(j=0;j<n;j++)
        {
            if(tree[j].parent==-1)            //检查未合并的结点
            {
                if(tree[j].weight<min1)
                {
                    min22=min11;
                    min11=j;
                    min2=min1;
                    min1=tree[j].weight;
                }
                else
                    if(tree[j].weight<min2)
                    {
                        min22=j;
                        min2=tree[j].weight;
                    }
            }
        }
        tree[min11].parent=i;             //当前合并结点1的父结点为新节点
        tree[min22].parent=i;             //当前合并结点2的父结点为新节点
        tree[i].weight=tree[min11].weight+tree[min22].weight;  //新结点的权值
        tree[i].lch=min11;
        tree[i].rch=min22;
        continue;
    }
    tree[2*n-2].parent=-1;               //令最后一个结点的parent为-1
}
main()
{
    struct node tree[N];
    int j,k,t,pr,s;
    int code[n][n];
    creat();
    for(i=0;i<n;i++)
    {
        t=i;                        //t记录当前结点位置
        k=n-2;                      //j表示当前结点所在层次
        while(tree[t].parent!=-1)   //当前结点不是根结点时
        {
            pr=tree[t].parent;
            if(t==tree[pr].lch) code[i][k]=0;       //左子树记为0
            else code[i][k]=1;                      //右子树记为1
            k=k-1;
            t=pr;
        }
        code[i][n-1]=k+1;          //记录编码起始位置
    }
    printf("\nhuffman编码为:");
    for(i=0;i<n;i++)
    {
        s=code[i][n-1];
        for(;s<n-1;s++)
        {
            printf("%c",tree[i].leaves);
            printf("%d",code[i][s]);
        }
        printf("\n");
    }
}




#3
Karryu2016-11-01 01:03
回复 2楼 书生牛犊
为什么合并结点的时候又出错了?
只有本站会员才能查看附件,请 登录

A结点的parent应该是7的 下面新结点的也是错的
#4
书生牛犊2016-11-01 08:13
你的设计原理就是错的。哈夫曼树是一个所有节点都是叶节点的树,也就是说任意结点都不会是其他节点的父节点!
只有本站会员才能查看附件,请 登录

这题要是我做,我会需要用到最小堆。每次弹出两个最小的数据,然后判断一下弹出的两个数据类型是否相同(即是不是都是叶节点ABCDE,或者都是结合过的子树(像step1中的7+10,11+12这类的)),如果不是再从最小堆中弹出一个数据,并取其中两个类型相同的数据合并子树,把合并生成的子树和类型不同的那个(如果有)压回最小堆,反复这个过程,直到最小堆中只剩下1个子树。
这个子树就是我们要的哈夫曼树。
然后根据该哈夫曼树输出各个节点的哈夫曼编码方案。
1