博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
哈夫曼树算法及C++实现
阅读量:7109 次
发布时间:2019-06-28

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

一、相关概念

  1、叶子结点的权值(weight)是对叶子结点赋予的一个有意义的数值量。

  2、设二叉树有n个带权值的叶子结点,从根节点到各个叶子结点的路径长度与相应叶子结点权值的乘积之和叫做二叉树的带权路径长度

  3、给定一组具有确定权值的叶子结点,可以构造出不同的二叉树,将其中带权路径长度最小的二叉树称为哈夫曼树

二、哈夫曼算法基本思想

  (1) 以权值分别为W1,W2...Wn的n各结点,构成n棵二叉树T1,T2,...Tn并组成森林F={T1,T2,...Tn},其中每棵二叉树 Ti仅有一个权值为 Wi的根结点;

  (2) 在F中选取两棵根结点权值最小的树作为左右子树构造一棵新二叉树,并且置新二叉树根结点权值为左右子树上根结点的权值之和(根结点的权值=左右孩子权值之和,叶结点的权值= Wi);

  (3) 从F中删除这两棵二叉树,同时将新二叉树加入到F中;

  (4) 重复(2)、(3)直到F中只含一棵二叉树为止,这棵二叉树就是Huffman树。

三、哈夫曼算法的存储结构

  考虑到对于有n个叶子结点的哈夫曼树有2n-1个结点,并且进行n-1次合并操作,为了便于选取根节点权值最小的二叉树以及合并操作,设置一个数组haftree[2n-1],保存哈夫曼树中的各个结点的信息,数组元素的结点结构如下图所示:

weight lchild rchild parent

                                 

 

  哈夫曼树的结点结构

其中,weight保存结点权值;

lchild保存该节点的左孩子在数组中的下标;

rchild保存该节点的右孩子在数组中的下标;

parent保存该节点的双亲孩子在数组中的下标。

可以用C++语言中的结构体类型定义上述结点,如下:

1 // 哈夫曼树的结点结构2 struct element3 {4     int weight;        // 权值域5     int lchild, rchild, parent;  // 该结点的左、右、双亲结点在数组中的下标6 };

 

四、哈夫曼算法C++实现

  为了判定一个结点是否已经加入哈夫曼树中,可通过parent域的值来确定。初始时parent的值为-1,当某结点加入到树中时,该节点parent域的值为其双亲结点在数组中的下标。

  构造哈夫曼树时,首先将n个权值的叶子结点存放到数组haftree的前n个分量中,然后不断将两棵子树合并为一棵子树,并将新子树的根节点顺序存放到数组haftree的前n个分量的后面。

  哈夫曼算法用伪代码描述为:

1、数组haftree初始化,所有数组元素的双亲、左右孩子都置为-1;2、数组haftree的前n个元素的权值置给定权值;3、进行n-1次合并    3.1 在二叉树集合中选取两个权值最小的根节点,其下标分别为i1,i2;    3.2 将二叉树i1、i2合并为一棵新的二叉树k。

  哈夫曼算法完整代码描述如下;

1 #include
2 #include
//这个头文件是声明一些 “流操作符”的 3 //比较常用的有:setw(int);//设置显示宽度,left//right//设置左右对齐。 setprecision(int);//设置浮点数的精确度。 4 using namespace std; 5 // 哈夫曼树的结点结构 6 struct element 7 { 8 int weight; // 权值域 9 int lchild, rchild, parent; // 该结点的左、右、双亲结点在数组中的下标10 };11 // 选取权值最小的两个结点12 void selectMin(element a[],int n, int &s1, int &s2)13 {14 for (int i = 0; i < n; i++)15 {16 if (a[i].parent == -1)// 初始化s1,s1的双亲为-117 {18 s1 = i;19 break;20 }21 }22 for (int i = 0; i < n; i++)// s1为权值最小的下标23 {24 if (a[i].parent == -1 && a[s1].weight > a[i].weight)25 s1 = i;26 }27 for (int j = 0; j < n; j++)28 {29 if (a[j].parent == -1&&j!=s1)// 初始化s2,s2的双亲为-130 {31 s2 = j;32 break;33 }34 }35 for (int j = 0; j < n; j++)// s2为另一个权值最小的结点36 {37 if (a[j].parent == -1 && a[s2].weight > a[j].weight&&j != s1)38 s2 = j;39 }40 }41 // 哈夫曼算法42 // n个叶子结点的权值保存在数组w中43 void HuffmanTree(element huftree[], int w[], int n)44 {45 for (int i = 0; i < 2*n-1; i++) // 初始化,所有结点均没有双亲和孩子46 {47 huftree[i].parent = -1;48 huftree[i].lchild = -1;49 huftree[i].rchild = -1;50 }51 for (int i = 0; i < n; i++) // 构造只有根节点的n棵二叉树52 {53 huftree[i].weight = w[i];54 }55 for (int k = n; k < 2 * n - 1; k++) // n-1次合并56 {57 int i1, i2; 58 selectMin(huftree, k, i1, i2); // 查找权值最小的俩个根节点,下标为i1,i259 // 将i1,i2合并,且i1和i2的双亲为k60 huftree[i1].parent = k;61 huftree[i2].parent = k;62 huftree[k].lchild = i1;63 huftree[k].rchild = i2;64 huftree[k].weight = huftree[i1].weight + huftree[i2].weight;65 }66 67 }   // 打印哈夫曼树68 void print(element hT[],int n)69 {70 cout << "index weight parent lChild rChild" << endl;71 cout << left; // 左对齐输出 72 for (int i = 0; i < n; ++i) 73 {74 cout << setw(5) << i << " ";75 cout << setw(6) << hT[i].weight << " ";76 cout << setw(6) << hT[i].parent << " ";77 cout << setw(6) << hT[i].lchild << " ";78 cout << setw(6) << hT[i].rchild << endl;79 }80 }81 int main()82 {83 int x[] = { 5,29,7,8,14,23,3,11 }; // 权值集合84 element *hufftree=new element[2*8-1]; // 动态创建数组85 HuffmanTree(hufftree, x, 8);86 print(hufftree,15);87 system("pause");88 return 0;89 }

最后的输出结果为:

 

参考文献:

[1]王红梅, 胡明, 王涛. 数据结构(C++版)[M]. 北京:清华大学出版社。

 2018-01-03

转载于:https://www.cnblogs.com/smile233/p/8184492.html

你可能感兴趣的文章
MySQL中Order By实现原理分析
查看>>
给视频加滚动字幕,给视频加字幕制作mv 录制的视频配背景音乐
查看>>
jquery获取复选框的值
查看>>
[zz]跳表(Skip List)的介绍以及查找插入删除等操作
查看>>
SAD和SATD的区别与几个名词解释
查看>>
C3P0配置实战
查看>>
Oracle问题之literal does not match format string
查看>>
shell的比较运算符
查看>>
ArcGIS JS 学习笔记2 实现仿百度的拖拽画圆
查看>>
BZOJ1026: [SCOI2009]windy数[数位DP]
查看>>
Nginx的https配置记录以及http强制跳转到https的方法梳理
查看>>
android图像处理系列之三--图片色调饱和度、色相、亮度处理
查看>>
TensorFlow学习路径【转】
查看>>
JAVA设计模式之单例模式
查看>>
Ansible@一个高效的配置管理工具--Ansible configure management--翻译(五)
查看>>
为啥百度、网易、小米都用Python?Python的用途是什么?
查看>>
Linux系统IO分析工具之iotop常用参数介绍
查看>>
软件的依赖关系:类图关系:is-a has-a use-a
查看>>
2010年美国计算机图书市场报告四:编程语言
查看>>
ME525+ MB525 android2.3.4获取ROOT权限和关闭震动(振动反馈)的方法分享
查看>>