zoukankan      html  css  js  c++  java
  • 哈夫曼树的建立

     

    一、实验目的

    1. 理解哈夫曼树及其应用。
    2. 掌握生成哈夫曼树的算法。

    二、实验原理

    哈夫曼树,即最优树,是带权路径长度最短的树。有着广泛的应用。在解决某些判定问题上,及字符编码上,有着重要的价值。

    构造一棵哈夫曼树,哈夫曼最早给出了算法,称为哈夫曼算法:

    (1)根据给定的N个权值   W1,W2,W3,……,Wn    ,构成N棵二叉树的集合F=     T1,T2,T3,……,Tn      ,其中每棵二叉树T1只有一个带权为Wi的根结点,其左右子树均空。

    (2)在 F中选出两棵根结点权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的权值为其左右子树上的根结点的权值之和。

    (3)在F中删除这两棵树,同时将新得到的加到F之中。重复(2)和(3),直至F中只剩一个为止。


    #include<stdio.h>
    #include<malloc.h>
    #include<string.h>
    #define MAXSIZE 100

    #include<stdio.h>
    #include<malloc.h>
    #define MAXSIZE 100
    typedef struct HTnode
    {  
         int weight;
         int parent,lchild,rchild;
    }STKzone;
    typedef STKzone *STK,*stack;

    typedef char **huffman;
    STK HT,tree,tree1;
     int a[20][20],count;
    STK creat(){
        int ye,number,quanzhi,shu1,shu2,shu3,i,jie,biao=0,min1=0,min2=1,j,k=0;
    //ye代表叶子的数目nnumber代表 需要开辟多少个空间quanzhi需要输入的叶子的权值
    //shu1代表第一个最小的数shu2代表第二个最小的数shu3代表shu1+shu2的和
    //min1,min2代表第一个最小数的下标,第二个最小数的下标
        printf(" 赫夫曼树的建立: ");
        printf("请输入权值(叶子)数目:");
        scanf("%d",&ye);
        while(ye<1){
            printf(" 输入错误,请重新输入权值数目:");
            scanf("%d",&ye);
            printf(" ");
        }
        if(ye==1){
            printf(" 只有一个权值,无须建立赫夫曼树! ");
        }else{
            number=ye*2-1;//需要开辟空间的数目
            tree=(struct HTnode *)malloc(number*sizeof(struct HTnode));//开辟空间
            printf(" 输入 %d权值(=>0),建立赫夫曼树: ",ye);
            count=ye;//编码用到
            for(i=0;i<ye;i++){
                scanf("%d",&quanzhi);//输入权植
                while(quanzhi<=0){//全职小于0,重新输入
                    printf(" 权值错(=>0),重新输入此权值: ");
                    scanf("%d",&quanzhi);
                }
            


                
                (tree+i)->weight=quanzhi;//给叶子的权值赋值
                (tree+i)->parent=0;
                (tree+i)->lchild=0;
                (tree+i)->rchild=0;
                biao=i;//biao 用来记当前链表中用了几个节点
            }
        }
     
        int wo1,wo2;
        

        while(true){//while start1
            for(i=0;i<=biao;i++)//找第一个最小的数
            {
                
                if(((tree+i)->parent)==0){//如果其父不为0,说明该节点已有父节点,则跳过该节点
                
                    if((tree+min1)->weight>(tree+i)->weight){
                        min1=i;//把最小的数的下表给min1


                    }
                }
            }

            if(min1==min2){//判断min1和min2是不是同一个位置的数
                    
                (tree+min1)->parent=-1;//如果min1和min2是同一个数,则把min1的父等于-1
                
                for(i=0;i<=biao;i++)//寻找第二个最小的数
                {
                
                    if((tree+i)->parent==0){
                        min2=i;
                        
                        break;
            
            
                    }
                }




            }else{//如果而这下标不想等的话,执行下面代码
            
                for(i=0;i<=biao;i++)
                {
                    if((tree+i)->parent==0){
                
                        if((tree+min2)->weight>(tree+i)->weight&&min1!=i){
                            min2=i;
        
                        }
                    }
                }
            }
            biao=biao+1;//因为链表中多了一个数据所以要+1
            shu1=0;shu2=0;//为shu1和shu2初始化
            wo1=0;wo2=0;//标志位,用来判断shu1和shu2书否被赋值
            for(i=0;i<=biao;i++){
                
                if(min1==i){
                    shu1=(tree+min1)->weight;//给shu1赋值
                    
                    wo1=1;
                }
                if(min2==i&&min1!=min2){
                    shu2=(tree+min2)->weight;//给shu2赋值
                    wo2=1;

                }

                if(wo1==1&&wo2==1){
                
                    shu3=shu1+shu2;
                    
                    (tree+biao)->weight=shu3;//该节点就是两个最小节点的父节点
                    (tree+biao)->lchild=min1;//把最小值的下表给父节点的lchild
                    (tree+biao)->rchild=min2;
                    
                    (tree+biao)->parent=0;//由于父节点现在还没有父节点,所以暂时=0
                    (tree+min1)->parent=biao;
                    (tree+min2)->parent=biao;//把父节点的下标给孩子
                    
                    
                    break;            
                
                
                
                
                }
                
            }
            min1=0;
            min2=1;

            for(i=0;i<=biao;i++)//为了给min1初始化
            {
                
                if((tree+i)->parent==0){
                    min1=i;
                    
                    break;
            
            
                }
            }
            for(i=0;i<=biao;i++)//为了给min2初始化
            {
                if((tree+i)->parent==0&&min1!=i){
                
                
                        min2=i;
                            
                    
                    
                    
                }
            }            
        
            if(biao==number-1){//如果链表满了就跳出循环 ,结束
                
                break;    
            }
        }//while end1


        return tree;
    }



     void huffmancode(){
        int i=0,start=0,c,f;
        huffman HC;
        char *cd;
        for(i=0;i<2*count-1;i++){
            printf("----%d---%d---%d---%d-- ",(tree+i)->parent,(tree+i)->lchild,(tree+i)->rchild,(tree+i)->weight);
        }

        HC=(huffman)malloc(count*sizeof(char *));
        cd=(char *)malloc(count*sizeof(char));
        cd[count-1]='';
        for(i=0;i<count;++i){//因为从叶子节点开始查找,所以循环的次数就等于叶子数
            start=count-1;
            for(c=i,f=(tree+i)->parent;f!=0;c=f,f=(tree+f)->parent)//循环结束的条件是f=0;
                if((tree+f)->lchild==c)
                    cd[--start]='0';
                else
                    cd[--start]='1';
            HC[i]=(char *)malloc((count-start)*sizeof(char));//开辟一个空间哈夫曼编码那么长的空间
            strcpy(HC[i],&cd[start]);//把cd里面的数据给hc
        
        }
        printf(" 对应的二进制赫夫曼编码为: ");
        for(i=0;i<count;++i){
            printf("%s",*(HC+i));
           printf("   ");
          }



    }
        
    int main()
    {
        
        tree1=creat();
        huffmancode();
       
        return 0;
    }/*main_end*/

  • 相关阅读:
    openVolumeMesh example 程序学习
    使用字符串创建java 对象
    HDU-1501-Zipper
    UVA-10285-Longest Run on a Snowboard
    HDU-2182-Frog
    HDU-2044-一只小蜜蜂
    POJ-1163-The Triangle
    HDU-1159-Common Subsequence
    HDU-2069-Coin Change
    HDU-4864-Task
  • 原文地址:https://www.cnblogs.com/huifeidezhuzai/p/9227358.html
Copyright © 2011-2022 走看看