哈夫曼树

来源:互联网 发布:招商银行外汇交易软件 编辑:程序博客网 时间:2024/05/24 06:25

点击打开链接

•哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。
输入:


•输入有多组数据。
•每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。
输出:
•输出权值。
样例输入:
•5 
•1 2 2 5 9
样例输出:
•37

算法一:

nclude<iostream>  #include<stack>  using namespace std;  int result[1001];  //哈夫曼树的权值就是除了所有叶子  

//的节点的权值的和  int main(){      int n,i,sum,num;      while(scanf("%d",&n)!=EOF){          memset(result,0,n);          for(i=0;i<n;i++)              scanf("%d",&result[i]);          //进行排序,从小到大          sort(result,result+n);          i=1;          sum=0;          while(i<n){              //每次都要进行重新排序,因为生成了新的节点             sort(result+i-1,result+n);             //计算父亲             num = result[i-1]+result[i];             sum+=num;             //将新的节点赋值             result[i]=num;             i++;          }          printf("%d\n",sum);      }      return 0;  }  
算法二:

#include <string.h>  #include <algorithm>  #include<iostream>  #include<stack>  #define maxvalue 0x7fffffff//这个是int的最大值  using namespace std;  //创建节点的结构体  struct huffman{      int weight;      int parent,lchild,rchild;  }list[5000];  int main()  {      int n,m;      int i,j;      int ans;      int x1,x2;//用来存放树生成过程中的最小和次小的角标      int m1,m2;//用来存放树生成过程中的最小和次小的值      while(scanf("%d",&n)!=EOF)      {          m=2*n-1; //生成2n-1个节点         for(i=0;i<m;i++)          list[i].parent=list[i].lchild=list[i].rchild=-1;          for(i=0;i<n;i++)          scanf("%d",&list[i].weight);          ans=0;          for(i=0;i<n-1;i++){              x1=x2=0;              m1=m2=maxvalue;              for(j=0;j<n+i;j++){                  //用来判断新的节点是否小于最小且没有双亲                  //如果小于最小的话就把当前的数和角标给x1和m1                  //并且在x1和m1中存入当前最小的角标和值                  if(list[j].weight<m1&&list[j].parent==-1){                      x2=x1;                      m2=m1;                      x1=j;                      m1=list[j].weight;                  }                 //用来判断是不是小于次小,如果小于的话就替换次小                  else if(list[j].weight<m2&&list[j].parent==-1){                      x2=j;                      m2=list[j].weight;                  }              }              list[x1].parent=n+i;              list[x2].parent=n+i;              list[n+i].lchild=x1;              list[n+i].rchild=x2;              list[n+i].weight=list[x1].weight+list[x2].weight;              ans+=list[n+i].weight;          }          printf("%d\n",ans);      }      return 0;  }  
算法三:这个是针对于此类型的题比较完整的算法,可我现在还不太理解,对指针还不熟悉,可能以后回过来看会理解。
/*示例 ****哈夫曼编码****请输入结点个数:8输入这8个元素的权值(均为整形):1:272:43:874:215:26:217:18:25*/#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct{  unsigned int weight;  //用来存储各个结点的权值   unsigned int parent,LChild,RChild;  //指向双亲、孩子结点的指针 } HTNode, *HuffmanTree;  //动态分配数组,存储哈夫曼树 typedef char *HuffmanCode;  //动态分配数组,存储哈夫曼树///选择两个parent为0,且weight最小的结点s1和s2 void Select(HuffmanTree *ht,int n,int *s1,int *s2){ int i,min; for(i=1; i<=n; i++) {   if((*ht)[i].parent==0)   {       min=i;       break;   } } for(i=1; i<=n; i++) {    if((*ht)[i].parent==0){      if((*ht)[i].weight<(*ht)[min].weight)      min=i;} } *s1=min; for(i=1; i<=n; i++) {    if((*ht)[i].parent==0 && i!=(*s1)){      min=i;      break;} } for(i=1; i<=n; i++) {    if((*ht)[i].parent==0 && i!=(*s1)){      if((*ht)[i].weight<(*ht)[min].weight)   min=i;} } *s2=min;}///构造哈夫曼树ht,w存放已知n个权值 void CrtHuffmanTree(HuffmanTree *ht,int *w,int n){ int m,i,s1,s2; m=2*n-1;    //总共的结点数  *ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); for(i=1; i<=n; i++)  //1-n号存放叶子结点,初始化  {  (*ht)[i].weight=w[i];  (*ht)[i].LChild=0;  (*ht)[i].parent=0;  (*ht)[i].RChild=0; } for(i=n+1; i<=m; i++)   //非叶子结点的初始化 {  (*ht)[i].weight=0;  (*ht)[i].LChild=0;  (*ht)[i].parent=0;  (*ht)[i].RChild=0; }  printf("\n?哈夫曼树为: \n"); for(i=n+1; i<=m; i++)   //创建非叶子结点,建哈夫曼树 { /*在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0且weight最小的结点,其序号分别赋值给s1、s2*/   Select(ht,i-1,&s1,&s2);  (*ht)[s1].parent=i;  (*ht)[s2].parent=i;  (*ht)[i].LChild=s1;  (*ht)[i].RChild=s2;  (*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;  printf("%d (%d, %d)\n",(*ht)[i].weight,(*ht)[s1].weight,(*ht)[s2].weight); } printf("\n");} //从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n){ char *cd;   //定义的存放编码的空间 int a[100]; int i,start,p,w=0; unsigned int c; hc=(HuffmanCode *)malloc((n+1)*sizeof(char *));  //分配n个编码的头指针 cd=(char *)malloc(n*sizeof(char));  //分配求当前编码的工作空间 cd[n-1]='\0';  //从右向左逐位存放编码,首先存放编码结束符 for(i=1; i<=n; i++)  //求n个叶子结点对应的哈夫曼编码 {  a[i]=0;  start=n-1;  //起始指针位置在最右边  for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent)  //从叶子到根结点求编码  {    if( (*ht)[p].LChild==c){cd[--start]='1';  //左分支标1a[i]++;}    else {cd[--start]='0';  //右分支标0a[i]++;}  }  hc[i]=(char *)malloc((n-start)*sizeof(char));  //为第i个编码分配空间  strcpy(hc[i],&cd[start]);    //将cd复制编码到hc } free(cd); for(i=1; i<=n; i++)  printf(" 权值为%d的哈夫曼编码为:%s\n",(*ht)[i].weight,hc[i]); for(i=1; i<=n; i++)    w+=(*ht)[i].weight*a[i]; printf(" 带权路径为:%d\n",w);}int main(){ HuffmanTree HT; HuffmanCode HC; int *w,i,n,wei;  printf("**哈夫曼编码**\n" ); printf("请输入结点个数:" ); scanf("%d",&n); w=(int *)malloc((n+1)*sizeof(int));  printf("\n输入这%d个元素的权值:\n",n);  for(i=1; i<=n; i++) {   printf("%d: ",i);   fflush(stdin);//清空输入缓冲区;   scanf("%d",&wei);  w[i]=wei; } CrtHuffmanTree(&HT,w,n); CrtHuffmanCode(&HT,&HC,n);  system("pause"); return 0;}


原创粉丝点击