【数据结构】二叉树的一个应用,哈夫曼编码的生成
2015-03-24 09:27
459 查看
1.哈夫曼树只有结点为0.或者结点为2的值。所以如果叶子结点为n的话,那么整个哈夫曼树的所有结点个数为2n-1;因为结点为2的结点个数n0=n2+1;所以总数n=n0+n2=2n0-1;
过程:<1>由已知的n个权值形成哈夫曼树的初态,即在数组ht[]的前n项中填入相应的权值。
<2>建立哈夫曼树。依次将数组ht[]中的第n+1项到第m项作为当前项,并进行以下处理:
1.在前已形成的项目中选择两个权值最小且无双亲的项。
2.将当前项的序号填入两个选择的项作为双亲,将两个选择项的序号填入当前项分别作为左右孩子。
3.将两个选择项的权值相加后填入当前项作为当前项的权值。
<3>由已形成的哈夫曼树求哈夫曼编码。对每个叶节点都进行如下处理:
扫描由叶节点到根节点的各条分支,若果分支中的当前结点与双亲关系是左支关系,则生成编码0,若分之中的当前结点与双亲结点是右支关系,则生成编码1,由此生成的二级制码的序列即为该结点的哈夫曼编码。
程序如下:
#include<iostream>
using namespace std;
#define maxlen 100
struct HaffNode
{
int weight;
int parent;
int lchild;
int rchild;
};
struct HaffCode
{
int bit[maxlen];
int start;
int weight;
};
void Haffman(int w[],int n,HaffNode ht[], HaffCode hc[])
{
int i, j, m1, m2, x1, x2;//m1,m2分别表示最小,次小的权值;x1,x2分别表示当前分支结点的左右儿子
//步骤1.构造哈夫曼树
for (i = 0; i < 2 * n - 1; i++)//哈夫曼树初始化
{
if (i < n)ht[i].weight = w[i];
else
ht[i].weight = 0;
ht[i].parent = 0;
ht[i].lchild = ht[i].rchild = -1;
}
for (i = 0; i < n - 1; i++)//构造哈夫曼树的n-1个分支结点
{
m1 = m2 = 1000;
x1 = x2 = 0;
for (j = 0; j < n + i; j++)
{
if (ht[j].weight < m1 && ht[j].parent == 0)
{
m2 = m1;//最小保存到次小
x2 = x1;
m1 = ht[j].weight;
x1 = j;
}
else if (ht[j].weight < m2 && ht[j].parent == 0)
{
m2 = ht[j].weight;
x2 = j;
}
}
ht[x1].parent = n + i;
ht[x2].parent = n + i;
ht[n + i].weight = ht[x1].weight + ht[x2].weight;
ht[n + i].lchild = x1;
ht[n + i].rchild = x2;
}
//步骤2 由哈夫曼树生成哈夫曼编码
HaffCode cd;
int child, parent;
for (i = 0; i < n; i++)//由哈夫曼树生成哈夫曼编码
{
cd.start = n - 1;
cd.weight = ht[i].weight;
child = i;
parent = ht[child].parent;
while (parent != 0)
{
if (ht[parent].lchild == child)
cd.bit[cd.start] = 0;
else
cd.bit[cd.start] = 1;
cd.start--;
child = parent;
parent = ht[child].parent;
}
for (j = cd.start + 1; j < n; j++)
hc[i].bit[j] = cd.bit[j];
hc[i].start = cd.start;
hc[i].weight = cd.weight;
}
}
int main(void)
{
int w[] = { 4, 2, 6, 8, 3, 2, 1 };
int n = 7, i, j;
HaffNode *ht = new HaffNode[2 * n - 1];
HaffCode *hc = new HaffCode
;
Haffman(w, n,ht, hc);
for (i = 0; i < n; i++)
{
cout << "weight=" << hc[i].weight << "code=";
for (j = hc[i].start + 1; j < n; j++)
cout << hc[i].bit[j];
cout << endl;
}
}
效果图:
过程:<1>由已知的n个权值形成哈夫曼树的初态,即在数组ht[]的前n项中填入相应的权值。
<2>建立哈夫曼树。依次将数组ht[]中的第n+1项到第m项作为当前项,并进行以下处理:
1.在前已形成的项目中选择两个权值最小且无双亲的项。
2.将当前项的序号填入两个选择的项作为双亲,将两个选择项的序号填入当前项分别作为左右孩子。
3.将两个选择项的权值相加后填入当前项作为当前项的权值。
<3>由已形成的哈夫曼树求哈夫曼编码。对每个叶节点都进行如下处理:
扫描由叶节点到根节点的各条分支,若果分支中的当前结点与双亲关系是左支关系,则生成编码0,若分之中的当前结点与双亲结点是右支关系,则生成编码1,由此生成的二级制码的序列即为该结点的哈夫曼编码。
程序如下:
#include<iostream>
using namespace std;
#define maxlen 100
struct HaffNode
{
int weight;
int parent;
int lchild;
int rchild;
};
struct HaffCode
{
int bit[maxlen];
int start;
int weight;
};
void Haffman(int w[],int n,HaffNode ht[], HaffCode hc[])
{
int i, j, m1, m2, x1, x2;//m1,m2分别表示最小,次小的权值;x1,x2分别表示当前分支结点的左右儿子
//步骤1.构造哈夫曼树
for (i = 0; i < 2 * n - 1; i++)//哈夫曼树初始化
{
if (i < n)ht[i].weight = w[i];
else
ht[i].weight = 0;
ht[i].parent = 0;
ht[i].lchild = ht[i].rchild = -1;
}
for (i = 0; i < n - 1; i++)//构造哈夫曼树的n-1个分支结点
{
m1 = m2 = 1000;
x1 = x2 = 0;
for (j = 0; j < n + i; j++)
{
if (ht[j].weight < m1 && ht[j].parent == 0)
{
m2 = m1;//最小保存到次小
x2 = x1;
m1 = ht[j].weight;
x1 = j;
}
else if (ht[j].weight < m2 && ht[j].parent == 0)
{
m2 = ht[j].weight;
x2 = j;
}
}
ht[x1].parent = n + i;
ht[x2].parent = n + i;
ht[n + i].weight = ht[x1].weight + ht[x2].weight;
ht[n + i].lchild = x1;
ht[n + i].rchild = x2;
}
//步骤2 由哈夫曼树生成哈夫曼编码
HaffCode cd;
int child, parent;
for (i = 0; i < n; i++)//由哈夫曼树生成哈夫曼编码
{
cd.start = n - 1;
cd.weight = ht[i].weight;
child = i;
parent = ht[child].parent;
while (parent != 0)
{
if (ht[parent].lchild == child)
cd.bit[cd.start] = 0;
else
cd.bit[cd.start] = 1;
cd.start--;
child = parent;
parent = ht[child].parent;
}
for (j = cd.start + 1; j < n; j++)
hc[i].bit[j] = cd.bit[j];
hc[i].start = cd.start;
hc[i].weight = cd.weight;
}
}
int main(void)
{
int w[] = { 4, 2, 6, 8, 3, 2, 1 };
int n = 7, i, j;
HaffNode *ht = new HaffNode[2 * n - 1];
HaffCode *hc = new HaffCode
;
Haffman(w, n,ht, hc);
for (i = 0; i < n; i++)
{
cout << "weight=" << hc[i].weight << "code=";
for (j = hc[i].start + 1; j < n; j++)
cout << hc[i].bit[j];
cout << endl;
}
}
效果图:
相关文章推荐
- 用Application Updater Block生成一个自我更新的WinForms 应用
- 一个应用二叉树基本算法的程序 zz
- 数据结构 - 把一个整数数组放到二叉树中使其有序(C++)
- 一个根据wsdl生成xfire stub的应用问题
- 微软等数据结构+算法面试100题(5)--怎样编写一个程序,把一个有序整数数组放到二叉树中
- 菜鸟QiFang学数据结构系列(一):一维数组的高级应用--一个可容纳超多位数的求N!的程序!
- 二叉树层序遍历应用:要求将所有结点加上一个m_pNext指针,指向同层右侧的结点,右侧若无结点则指向NULL,写出其中的Connect函数。
- 数据结构-------树与二叉树的几个简单应用
- console.log的一个应用 -----用new方法生成一个img对象和document.createElement方法创建一个img对象的区别
- 数据结构_二叉树_遍历算法应用
- 用Application Updater Block生成一个自我更新的WinForms 应用(amart client)
- set,bitset 的一个应用实例——数据结构和比较算法
- 代码生成工具应成为中国外包公司的一个应用策略
- SDUT 1291数据结构上机测试4.1:二叉树的遍历与应用1
- 简易计算器设计中的一个数据结构问题——Ada应用实例之二
- 一个应用二叉树基本算法的程序
- linux下libxml2应用--生成一个tree并且保存为xml文件
- bo2-32.cpp 一个数组可生成若干静态链表(数据结构由c2-3.h定义)的基本操作(12个)
- poj 3522 Slim Span (最小生成树 的 一个性质 kruskal 的 应用 )
- 数据结构--二叉树--输出树中从根到每个叶子节点的路径(树遍历算法的应用) .