标题:Huffman树的建立
只看楼主
Karryu
Rank: 1
等 级:新手上路
帖 子:37
专家分:0
注 册:2016-5-5
结帖率:90%
已结贴  问题点数:12 回复次数:3 
Huffman树的建立
程序代码:
#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树的程序是哪里出错了
在输入结点时那个循环也不正常 会出现

这样的情况
然后下面运行出错
收到的鲜花
  • 书生牛犊2016-11-01 08:37 送鲜花  50朵   附言:提问很规范,送分
搜索更多相关主题的帖子: leaves parent 
2016-10-29 21:32
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
得分:12 

程序代码:
#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");
    }
}





φ(゜▽゜*)♪
2016-10-29 23:53
Karryu
Rank: 1
等 级:新手上路
帖 子:37
专家分:0
注 册:2016-5-5
得分:0 
回复 2楼 书生牛犊
为什么合并结点的时候又出错了?

A结点的parent应该是7的 下面新结点的也是错的
2016-11-01 01:03
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
得分:0 
你的设计原理就是错的。哈夫曼树是一个所有节点都是叶节点的树,也就是说任意结点都不会是其他节点的父节点!

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

φ(゜▽゜*)♪
2016-11-01 08:13



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




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

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