当前位置:   article > 正文

贪心算法 之 哈夫曼编码_贪心法实现哈夫曼编码问题和多机调度算法

贪心法实现哈夫曼编码问题和多机调度算法

贪心算法 之 哈夫曼编码

 

1.最优二叉树:(哈夫曼树)

1>结点的权:赋予叶子结点以个有意义的值;

2>结点的路径长度:从根结点到当前结点的的长度

结点的带权路径长度:W*L (W:权 L:路径长度)

3>二叉树的带权路径长度:一颗二叉树的所有叶子结点的带权路径长度之和

 

4>最优二叉树:一颗二叉树的带权路径最小,就是最优二叉树

2.哈夫曼树的特点:

1>没有单分支;

2>当叶子为n时,双亲为n-1;

构造一颗哈夫曼树:

(1)根据给定的n个权值{w1, w2,…,wn},构成n棵二叉树的集合F= {T1, T2,…,Tn},其中每棵二叉树Ti中只有一个带权为wi的根节点,其左右子树均空。

在F中选取两棵权值最小的二叉树作为左、右子树构造一棵新的二叉树,置新 构造二叉树的根节点的权值为其左、右子树根节点的权值之和。

从F中删除这两棵树,同时将新得到的二叉树加入到F中。

重复(2)、(3),直到F中只含一棵树时为止。这棵树便是最优二叉树(哈夫曼树)。 从以上叙述可知,哈夫曼树中权值最小的两个节点互为兄弟节点。

例子:

设有一英文文章,共有A,B,C,D四种字符,它们的出现频率依次为F{9,3,6,4},

 

算法一:链式哈夫曼树

思想:

1>从森林{9,3,6,4}中选取最小和次小的两颗二叉树构成一颗新的二叉树,并放回森林。(左子女最小,右子女次小)

2>重复第一步,直到森林中只剩一颗二叉树;

 

 

算法描述:实现链式哈夫曼树:

数据结构:结点:

typedef struct node{

char word;

int weight;

struct node *left,*right;

}HufNode;

森林:

有N个叶子结点的初始森林(数组)

1>定义森林:

  1. HufNode **F;
  2. F=(HufNode**)malloc(n*sizeof(HufNode*));

2>初始化森林:

  1. HufNode *p;
  2. char a[]={A,B,C,D};
  3. int b[]={9,3,6,4};
  4. for(int i=0;i<n;i++){
  5. p=(HufNode*)malloc(sizeof(HufNode));
  6. p->word=a[i];
  7. p->right=p->left=^;
  8. F[i]=p;
  9. }

实现最优二叉树:

 

 

  1. for(int loop=1;loop<n;loop++){ //找n-1次最小次小
  2. 复习:找最小次小;
  3. min=0;
  4. minx=1;
  5. for(int i=1;i<n;i++){
  6. if(a[i]<a[min]){
  7. minx=min;
  8. min=i;
  9. }
  10. else if(a[i]<a[minx])
  11. minx=i;
  12. }
  13. }

实践 1 //第一种 找最小次小,解决重复值,含^的情况

  1. for(int i=1;i<n;i++){
  2. int min,minx,t; //最小,次小
  3. for(min=0;min<n&&(!F[min]);min++); //找到第一个非空元素
  4. for(minx=min+1;minx<n&&(!F[min]);minx++); //找到第二个非空元素
  5. for(t=minx;t<n;t++){ //找最小次小
  6. if(F[t]){
  7. if(F[t]->weight<F[min]->weight){
  8. minx=min;
  9. min=t;
  10. }
  11. else if(F[t]->weight<F[minx]->weight){
  12. minx=t;
  13. }
  14. }
  15. }

生成二叉树;

  1. p=(HufNode*)malloc(sizeof(HufNode)); //生成双亲结点
  2. p->word=‘x’;
  3. p->weight=F[min]->weight+F[minx]->weight;
  4. p->left=F[min]; //最小
  5. p->right=F[minx]; //次小
  6. F[min]=p; //放回数组
  7. F[minx]=^;
  8. }

哈夫曼树的输出:

 

 

算法二:以数组实现哈夫曼树

1.存储:

  1. typedef struct{
  2. char word;
  3. int weight;
  4. int left,right,parent;
  5. int *cale //编码
  6. }Huff;

实现结构体数组:

 

                                                                                                                   6=2*4-1

  1. Huff *F;
  2. F=(Huff*)malloc((2*n-1)sizeof(Huff));
  3. //初始化
  4. for(int i=4;i<n;i++){
  5. printf("请输入:");
  6. scanf("%c",&ch);
  7. F[i].word=ch;
  8. scanf("%d",&we);
  9. F[i].weight=we;
  10. }
  11. //建立关系:
  12. int i,min,minx;
  13. for(int loop=0;loop<n-1;loop++){
  14. for(min=0;min<n+loop&&F[min].parint!=-1;min++);
  15. for(minx=0;i<minx+loop&&F[minx].parint!=-1;minx++);
  16. for(i=0;i<n+loop;i++){
  17. }
  18. }

编码:

例:给B编码,找到B的双亲结点,判断B是双亲的左子女还是右子女,来编码一位,再查找双亲的双亲,循环执行,直到找到根结点为止。

存储结构:

用一个n-1的int数组来存放编码,下标为0的空间存放编码长度(岗哨),从下标1开始正式存放编码。

C语言描述:

 

  1. //哈夫曼编码 数组实现
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. typedef struct node{
  5. char word; //字符
  6. int weight; //字符的权
  7. int left; //左子女的下标
  8. int right; //右子女的下标
  9. int parint; //双亲结点的下标
  10. int *code; //编码数组的首地址
  11. }Huffnode;
  12. void CreatHuffmanTree(Huffnode *F,int n); //函数声明
  13. void CreatHuffmancode(Huffnode *F,int n);
  14. void PrintHuffmancode(Huffnode *F,int n);
  15. int main (void){
  16. Huffnode *F;
  17. int n,w[4]={9,3,6,4};
  18. char ch[4]={'A','B','C','D'};
  19. printf("请输入:");
  20. scanf("%d",&n);
  21. //创建森林
  22. F=(Huffnode*)malloc((2*n-1)*sizeof(Huffnode));
  23. for(int i=0;i<n;i++){
  24. F[i].word=ch[i];
  25. F[i].weight=w[i];
  26. F[i].left=F[i].right=F[i].parint=-1;
  27. }
  28. //创建哈夫曼树
  29. CreatHuffmanTree(F,n);
  30. //创建 哈夫曼编码
  31. CreatHuffmancode(F,n);
  32. //输出
  33. PrintHuffmancode(F,n);
  34. free(F);
  35. }
  36. void CreatHuffmanTree(Huffnode *F,int n){ //创建哈夫曼树
  37. int loop=0;
  38. int k1,k2;//最小次小
  39. for(loop=0;loop<n-1;loop++){
  40. for(k1=0;k1<n+loop&&F[k1].parint!=-1;k1++); //找到第一个元素
  41. for(k2=k1+1;k2<n+loop&&F[k2].parint!=-1;k2++); //找到第二个元素
  42. for(int i=k2;i<loop+n;i++){ //找到最小,次小
  43. if(F[i].parint==-1){
  44. if(F[i].weight<F[k1].weight){
  45. k2=k1;
  46. k1=i;
  47. }
  48. else if(F[i].weight<F[k2].weight){
  49. k2=i;
  50. }
  51. }
  52. }
  53. F[n+loop].weight=F[k1].weight+F[k2].weight;
  54. F[n+loop].left=k1; //最小在左子女
  55. F[n+loop].right=k2; //次小在右子女
  56. F[n+loop].parint=-1;
  57. F[n+loop].word='X';
  58. F[k1].parint=F[k2].parint=n+loop;
  59. }
  60. }
  61. void CreatHuffmancode(Huffnode *F,int n){ //创建哈夫曼编码
  62. int c,pa;
  63. int *p;
  64. for(int i=0;i<n;i++){
  65. F[i].code=p=(int*)malloc(n*sizeof(int));
  66. p[0]=0; //p[0]用来充当岗哨
  67. c=i;
  68. while(F[c].parint!=-1){ //当找到根结点时终止循环
  69. pa=F[c].parint;
  70. if(c==F[pa].left){
  71. p[++p[0]]=0;
  72. }
  73. else{
  74. p[++p[0]]=1;
  75. }
  76. c=pa; //再找双亲的双亲
  77. }
  78. }
  79. }
  80. void PrintHuffmancode(Huffnode *F,int n){
  81. for(int j=0;j<n;j++){
  82. printf("%c的编码是:",F[j].word);
  83. for(int i=F[j].code[0];i>0;i--){ //由子女找双亲,编的码,故倒着输出
  84. printf("%d",F[j].code[i]);
  85. }
  86. printf("\n");
  87. }
  88. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/693641
推荐阅读
相关标签
  

闽ICP备14008679号