博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
哈夫曼树
阅读量:4991 次
发布时间:2019-06-12

本文共 4247 字,大约阅读时间需要 14 分钟。

装载请注明涞源
 
哈夫曼树的基本概念
 
哈夫曼树(Huffman Tree),又叫最优二叉树,指的是对于一组具有确定权值的叶子结点的具有最小带权路径长度的二叉树。
 
(1)路劲(Path):从树中的一个结点到另一个结点之间的分支构成两个结点间的路径。
(2)路径长度(Path Length):路径上的分支树。
(3)树的路径长度(Path Length of Tree):从树的根结点到每个结点的路径长度之和。在结点数目相同的二叉树中,完全二叉树的路径长度最短。
(4)结点的权(Weight of  Node):在一些应用中,赋予树中结点的一个有实际意义的树。
(5)结点的带权路径长度(Weight Path Length of Node):从该结点到树的根结点的路径长度与该结点的权的乘积。
(6)树的带权路径长度(WPL):树中所有叶子结点的带权路径长度之和,记为           

 
在下图所示的四棵二叉树,都有4个叶子结点,其权值分别1、2、3、4,他们的带权路径长度分别为:
 
(a)WPL = 1 x 2 + 2 x 2 + 3 x 2 + 4 X 2 = 20
(b)WPL = 1 x 1 + 2 x 2 + 3 x 3 + 4 x 3 = 28
(c)WPL  = 1 x 3 + 2 x 3 + 3 x 2 + 4 x 1 = 19
(d)WPL = 2 x 1 + 1 x 2 + 3 x 3 + 4 x 3 = 29
其中,(c)图所示的二叉树的带权路径长度最小,这棵树就是哈夫曼树。可以验证,哈夫曼树的带权路径长度最小。
 
哈夫曼树的构造算法
 
假设有n个权值,则构造出得哈夫曼树有n个叶子结点。n个权值分别设为w1,w2,...,wn,则哈夫曼树的构造规则为:
 
(1)将w1,w2,...,wn看成是有n棵树的森林(每棵树仅有一个结点);
(2)在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
 
下面我们实现一下吧!
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define MAX 4
  4. int input_weight(int *p)
  5. {
  6.     int i = 0;
  7.     for(i = 0;i < MAX;i ++)
  8.     {
  9.         scanf("%d",p + i);
  10.     }
  11.     while(getchar()!= '\n');
  12.         
  13.     return 0;
  14. }
  15. int order_weight(int *p)
  16. {
  17.     int i = 0;
  18.     int j = 0;
  19.     int temp;
  20.     for(i = 0;i < MAX;i ++)
  21.     {
  22.         for(j = 0;j < MAX - i - 1;j ++)
  23.         {
  24.             if(p[j] > p[j+1])
  25.             {
  26.                 temp = p[j];
  27.                 p[j] = p[j+1];
  28.                 p[j+1] = temp;
  29.             }
  30.         }
  31.     }
  32.     return 0;
  33. }
  34. //哈夫曼树结点
  35. typedef struct HuffNode
  36. {
  37.     int weight;
  38.     struct HuffNode *rchild;
  39.     struct HuffNode *lchild;
  40.     
  41. }HuffMan;
  42. //队列设计
  43. typedef struct _node_
  44. {
  45.     HuffMan *data;
  46.     struct _node_ *next;
  47. }ListNode;
  48. typedef struct
  49. {
  50.     ListNode *front;
  51.     ListNode *rear;
  52. }Queue;
  53. //create empty queue
  54. Queue *create_empty_queue()
  55. {
  56.     ListNode *HList;
  57.     Queue *Hqueue;
  58.     HList = (ListNode *)malloc(sizeof(ListNode));
  59.     HList->next = NULL;
  60.     
  61.     Hqueue = (Queue *)malloc(sizeof(Queue));
  62.     Hqueue->front = Hqueue->rear = HList;
  63.     return Hqueue;
  64. }
  65. //入队
  66. int EnterQueue(Queue *head,HuffMan *data)
  67. {
  68.     ListNode *temp;
  69.     temp = (ListNode *)malloc(sizeof(ListNode));
  70.     temp->data = data;
  71.     temp->next = NULL;
  72.     head->rear->next = temp;
  73.     head->rear = temp;
  74.     return 0;
  75. }
  76. //有序插入结点
  77. int OrderEnterQueue(Queue *head,HuffMan *p)
  78. {
  79.     ListNode *m = head->front->next;
  80.     ListNode *n = head->front;
  81.     ListNode *temp;
  82. #if 0
  83.     if(head->front->next == NULL)
  84.     {
  85.         printf("emty!\n");
  86.         temp = (ListNode *)malloc(sizeof(ListNode));
  87.         temp->data = p;
  88.         temp->next = NULL;
  89.         n->next = temp;
  90.         head->rear = temp;
  91.     }
  92. #endif
  93.     while(m)
  94.     {
  95.         if(m->data->weight < p->weight)
  96.         {
  97.             m = m->next;
  98.             n = n->next;
  99.         }
  100.         else{
  101.             
  102.             break;
  103.         }
  104.     }
  105.     //插到最后一个结点
  106.     if(m == NULL)
  107.     {
  108.         temp = (ListNode *)malloc(sizeof(ListNode));
  109.         temp->data = p;
  110.         temp->next = NULL;
  111.         n->next = temp;
  112.         head->rear = temp;
  113.     }
  114.     //插入中间结点
  115.     temp = (ListNode *)malloc(sizeof(ListNode));
  116.     temp->data = p;
  117.     n->next = temp;
  118.     temp->next = m;
  119.     return 0;
  120. }
  121. //判断队列是否为空(注意,我们认为队列含有一个结点为空,想想为什么
  122. //这样做?
  123. int is_empty_queue(Queue *head)
  124. {
  125.     if(head->front->next->next == NULL)
  126.     {
  127.         printf("is_empty_queue\n");
  128.         return 1;
  129.     }
  130.     
  131.     return 0;
  132. }
  133. //出队
  134. HuffMan *DeleteQueue(Queue * head)
  135. {
  136.     ListNode *temp;
  137.     temp = head->front;
  138.     head->front = temp->next;
  139.     free(temp);
  140.     temp = NULL;
  141.     return head->front->data;
  142. }
  143. //将结点按权值从小到大放入队列
  144. int create_forest(Queue *head,int *p)
  145. {
  146.     int i = 0;
  147.     HuffMan *temp;
  148.     for(i = 0;i < MAX;i ++)
  149.     {
  150.         temp = (HuffMan *)malloc(sizeof(HuffMan));
  151.         temp->weight = p[i];
  152.         temp->rchild = temp->rchild = NULL;
  153.         EnterQueue(head,temp);
  154.     }
  155.     return 0;
  156. }
  157. //创建哈夫曼树
  158. HuffMan *create_huffman_tree(Queue *head)
  159. {
  160.     HuffMan *right,*left,*current;
  161.     //循环结束时,队列只含有一个结点
  162.     while(!is_empty_queue(head))
  163.     {
  164.         left = DeleteQueue(head);
  165.         right = DeleteQueue(head);
  166.         current = (HuffMan *)malloc(sizeof(HuffMan));
  167.         current->weight = left->weight + right->weight;
  168.         current->rchild = right;
  169.         current->lchild = left;
  170. #if 0
  171.         printf("%d\n",left->weight);
  172.         printf("%d\n",right->weight);
  173.         printf("%d\n",current->weight);
  174. #endif
  175.         OrderEnterQueue(head,current);
  176.         
  177.     }
  178.     return head->front->next->data;
  179. }
  180. //访问结点
  181. int vist_node(HuffMan *p)
  182. {
  183.     printf("%d ",p->weight);
  184.     return 0;
  185. }
  186. //树的中序遍历
  187. int InOrder(HuffMan *p)
  188. {
  189.     if(p != NULL)
  190.     {
  191.         InOrder(p->lchild);//
  192.         vist_node(p);//
  193.         InOrder(p->rchild);//
  194.     }
  195.     return 0;
  196. }
  197. int main()
  198. {
  199.     int Wbuf[MAX];
  200.     Queue *head;
  201.     HuffMan *root;
  202.     //输入权值
  203.     input_weight(Wbuf);
  204.     //排序权值
  205.     order_weight(Wbuf);
  206.     //创建空队列
  207.     head = create_empty_queue();
  208.     //将结点按权值从小到大放入队列
  209.     create_forest(head,Wbuf);
  210.     //创建哈夫曼树
  211.     root = create_huffman_tree(head);
  212.     //中序遍历
  213.     InOrder(root);
  214.     printf("\n");
  215.         
  216.     return 0;
  217. }
运行结果:
 

转载于:https://www.cnblogs.com/xiao-wei-wei/p/3354496.html

你可能感兴趣的文章
中纪委:抗震中官员临危退缩玩忽职守将被严处
查看>>
MySQL 8.0.12 基于Windows 安装教程
查看>>
在hue中使用hive
查看>>
eclipse快捷键
查看>>
在指定文本里记录内容
查看>>
Android WebView常见问题及解决方案汇总
查看>>
[BZOJ4025]二分图
查看>>
HTML5 Canvas玩转酷炫大波浪进度图
查看>>
创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段
查看>>
电话录音系统说明书
查看>>
JVM(1)——IDEA启动分配内存大小及GC日志打印
查看>>
oracle 批量更新之update case when then
查看>>
text3
查看>>
自己写的连击文字特效
查看>>
【Android】eclipse打不开的解决办法和“Jar mismatch! Fix your dependencies”的解决
查看>>
Mysql查询某字段值重复的数据
查看>>
Java 自学笔记-基本语法3setOut()方法设置新的输出流
查看>>
cocos2d-JS 模块 anysdk 概述
查看>>
docker镜像mac下保存路径
查看>>
docker使用 命令
查看>>