C/C++实现哈夫曼树和生成哈夫曼编码

用C语言实现哈夫曼树和生成哈夫曼编码,首先生成哈夫曼树,哈夫曼树是从中选取权值最小的两个进行相加,将这两个分别做为生成的左子树和右子树,左子树要比右子树小。然后将相加得到的值从新放入,然后又从中找到最小的两个值,然后用这个两个值一直相加,直到只剩最后一个值,将这个值作为哈夫曼树的根。
生成哈夫曼编码,如果是左子树的话为0,右子树的话为1,从父节点还是往下找。然后这串代码就是哈夫曼编码。

上代码




 #include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h>


using namespace std;


const int Lsize  = 1000000;

typedef struct{

   int order;//序号
   char character;//字符值
   int weight;//权重
   int parent;
   int lift_Child;
   int right_Child;
   int deep;
   int code[100];//哈夫曼编码
}Nodetree,*HuffmanTree;


typedef struct node{

   char symbol;
   int quantity;
   struct node *next;
}Node;




int getListSize(char *pStr){

    int len=0;
    char *start = pStr;
    while(*start){
        len++;
        start++;
    }
    return len;
}

int getLIstLink(Node *head){

   int a = 0;
   Node *p = head->next;
   while(p){
     a++;
     p = p->next;
   }
   return a;
};

//打印链表
void print(struct node *head){

    struct node *p ;
    printf("开始打印\n");
    p=head->next ;
    if(p == NULL){
        printf("值为空\n");
    }
    while(p!=NULL){
     printf("          %c",p->symbol);
     printf("         %d\n",p->quantity);
     p=p->next;
    }
};



int QueryNOde(Node *head,char ch){

    Node *p;
    p = head->next;
    while(p!=NULL){
        if(p->symbol == ch){
            p->quantity = p->quantity + 1;//字符存在节点加1
            return 1;//这个字符已经存在
        }
        p = p->next;
    }
   return 0;//这个字符不存在
};

//生成权值
Node *createWeight(char *str){

    Node *head , *q ,*p;
    int list_size = getListSize(str);
    q=head=(struct node*)malloc(sizeof(struct node));
     for(int i = 0 ; i < list_size ; i++){
            //printf("当前的值:%c\n",*str);
            if(QueryNOde(head,*str)==1){//如果该数据已经存在,则节点加1
                  //  printf("开始遍历\n");
                // Node *boos = head = (struct node*)malloc(sizeof(struct node));
                   // printf("开始查找\n");
                // while(boos){
                  //  printf("进入查找\n");
                   // printf("当前遍历值为:%c\n",boos->symbol);
                   // if(boos->symbol == *str){
                      //  printf("开始修改值\n");
                       // boos->quantity = boos->quantity + 1;
                       // printf("值相同\n");
                       // break;
                   // }
                   // boos = boos->next;
                 //}
                } else{//生成新的权值
                    p = (struct node*)malloc(sizeof(struct node));
                    p->quantity = 1;
                    p->symbol = *str;
                    p->next = NULL;
                    q->next = p;
                    q = p;
                    //printf("值不同\n");
                }
                 str++;
            }
            return head;
};


void createTree(HuffmanTree &root,int n,Node *head){

    if(n<=0){
        return;
    }
    Node *q;
    q = head->next;
    int length = 2*n - 1;
    printf("n is %d\n",n);
    int HFCode[100];//哈夫曼编码数组
    root = new Nodetree[length+1];
    //初始化哈夫曼树
    for(int i = 1;i<=length;i++){
        root[i].order = i;
        root[i].character = 0;
        root[i].parent = 0;
        root[i].lift_Child = 0;
        root[i].right_Child = 0;
    }
    //给哈夫曼树赋值
    for(int i = 1;i<=n;i++){
        root[i].character = q->symbol;
        root[i].weight = q->quantity;
        q = q->next;
    }


    //开始建立哈夫曼树

      for(int i = n+1; i <=length; i++){  //进行 n-1 次循环建立哈夫曼树
        //k1表示森林中具有最小权值的树根结点的下标,k2为次最小的下标
        int k1 = -1 , k2;
        for(int j = 0; j < i; j++){
            if ( root[j].parent == 0  && k1 == -1 && root[j].weight > 0){
                k1 = j;
                continue;
            }
            if (root[j].parent == 0 && root[j].weight > 0){
                k2 = j;
                break;
            }
        }
        //将指针数组中的指针指向的最小值赋值给索引号为k1的,次小值赋值给索引号为k2的
        for (int j = k2; j < i; j++){
            if(root[j].parent == 0 ){
                if(root[j].weight < root[k1].weight){
                    k2 = k1;
                    k1 = j;
                }else if(root[j].weight < root[k2].weight){
                    k2 = j;
                }
            }
        }
        //开始生成新的哈夫曼树节点
        root[k1].parent = i;
        root[k2].parent = i;
       // printf(" i is:%d\n",i);
       // printf("k1 is :%d\n",k1);
       // printf("k2 is :%d\n",k2);
       // printf(" k1 weight is:%d\n",root[k1].weight);
       // printf(" k2 weight is:%d\n",root[k2].weight);
        root[i].order = i;
        root[i].lift_Child = k1;
        root[i].right_Child = k2;
        root[i].weight = root[k1].weight + root[k2].weight;
      }
          int start;
         // HFCode[n-1]='\0';
         //生成哈夫曼编码
      for(int i = 1;i<=n;i++){
          start = 0;
          int deep = 0;//节点的深度
          int c = i;
          int f = root[i].parent;
          while(f!=0){
            //printf("tart is:%d\n",start);
            if(root[f].lift_Child == c){
                root[i].code[start] = 0;//如果为左子树就为0
            }else{
               root[i].code[start] = 1;//右子树就为1
            }
            deep++;
            start++;
            c = f;
            f = root[f].parent;
          }
          root[i].deep = deep;
         // printf("code is:%d\n",root[i].code[start]);
      }

};



//void CreatHFCode(Nodetree *root,)
//打印哈夫曼树的表态结构
void printTree(Nodetree *root,int n){

   int length = 2*n -1;
   for(int i = 1 ;i<=length;i++){
    printf("order is %d   character is %c"   "  parent is %d  LiftC is %d  rightC is %d   weight is %d  deep is %d   ",root[i].order, root[i].character, root[i].parent,root[i].lift_Child,root[i].right_Child, root[i].weight,root[i].deep);
       int deep = root[i].deep;
         printf("HFCode is  :");
        for(int j=deep-1;j>=0;j--){
            printf("%d",root[i].code[j]);
        }
        printf("\n");
   }

};

 void QueryCOde(Nodetree *root,int n){

     int query_list[100];//哈夫曼编码整数数组
     int flag ;//哈夫曼编码匹配判断标志
     int c;
     int code_Size;
     char query_char[100];//用来接收哈夫曼编码
     scanf("%s",&query_char);
     //printf("%s\n",query_char);
     code_Size = getListSize(query_char);//输入的哈夫曼编码长度

     //将输入的哈夫曼编码有字符数组转换为整数数组
     for(int i = 0;i<code_Size;i++){
        c = query_char[i]-'0';
        query_list[i] = c;
       // printf("n is:%d\n",c);
     }

   // for(int i=0;i<code_Size;i++){
       //  printf("%d ",query_list[i]);
    // }

     for(int i=1;i<=n;i++){
        int deep = root[i].deep;
        int j ;
        //若哈夫曼的深度和输入的哈夫曼编码长度相同则开始查找
        if(deep==code_Size){
            //printf("deep is:%d code_size is:%d\n",deep,code_Size);
             j=0;
             int code = code_Size-1;
            deep--;
            //开始匹配值
            flag = i;
            while(deep>=0){
           // printf("开始匹配deep %d\n",deep);
            if(root[i].code[j]!=query_list[code]){
               //printf("值不相同\n");
               flag = -1;
               break;
            }
            j++;
            code--;
            //printf("%d deep is %d\n",i,deep);
            deep--;
        }
        }
        //判断是否找到对应的权重的值
       // printf("deep is:%d\n",deep);
        if(deep<0){
            flag = i;
            i = n+1;
        }

     }
    // printf("flag is:%d\n",flag);
     if(flag>0){
        printf("翻译结果值:%c\n",root[flag].character);
     }
     else{
        printf("没有与编码匹配的数据值\n");
     }

 };



int main()
{
    int Link_size ;
    struct node *head;
    Nodetree *root;
    char input_list[Lsize];



     printf("........................功能列表...................\n");
     printf("..............         输入报文  ................\n");
     printf("..............         打印频度  ................\n");
     printf("..............         建立哈夫曼树  ................\n");
     printf("..............         翻译报文  ................\n");
     //printf("..............         5.退出  ................\n");





    printf("..............输入想要赋值的字符串\n");
    scanf("%s",&input_list);
    gets(input_list);
    printf("%s\n",input_list);
    head = createWeight(input_list);
    printf("..............出现频度为\n");
    print(head);
    Link_size = getLIstLink(head);
    printf("..............链表长度为:%d\n",Link_size);
    createTree(root,Link_size,head);
    printTree(root,Link_size);

    int flag = 1;
    while(flag==1){
        printf("..............输入你想要查找的代码\n");
        QueryCOde(root,Link_size);
        printf("..............想继续查找输入1,不想输入0\n");
        scanf("%d",&flag);
    }

}

代码里面有备注,不清楚的可以留言,有错误的欢迎指出。

发布了34 篇原创文章 · 获赞 15 · 访问量 3238

猜你喜欢

转载自blog.csdn.net/weixin_43404016/article/details/94391366