哈夫曼树是带权路径最小的一种特殊二叉树,所以也称最优二叉树。 在这里不讨论基本概念如如何计算路径等,而只着重于树的创建,具体过程让我们举例而言。
其基本的原理为:将所有节点一开始都视为森林,每次从森林中选取两个根节点权值最小的树合并为一棵新树,新树的根节点大小为两个子节点大小的和,并将这棵新树重新加入到森林中。 如此一来每一轮操作都可以简化为两个基本操作:合并两棵树、插入新树,直到森林中只剩下一棵树,即是哈夫曼树。
以7个节点的权值分别为 1 3 7 9 12 18 25而言 创建的第一步:合并1、3,新增4
创建的第二步:合并4、7,新增11
创建的第三步:合并9、11,新增20
创建的第四步:合并12、18,新增30
创建的第五步:合并20、25,新增45
合并最后两棵树,得到哈夫曼树
在程序中我们实际运行来创建这棵树后,进行先序遍历的结果如下:
可以看到所有操作是符合结果的
在创建的过程中,很重要的一个过程是:每次都必须从森林中选出节点权值最小的两棵树进行合并,然后插入森林中,这个过程我们可以用最大最小堆的插入和删除来实现,关于最大最小堆的实现和讲解可以看dalao的这篇客: http://blog.csdn.net/ava1anche/article/details/46965675
实现代码
#include<iostream>
using
namespace std;
int cost =
0;
const
int MAX_CAPACITY =
100000;
enum type{Maxiumn,Miniumn};
typedef struct Node
{
int weight;
Node* Leftchild;
Node* Rightchild;
};
Node flag;
typedef struct Huffmantree
{
int size;
Node
*tree[MAX_CAPACITY];
};
Huffmantree Trees;
void insertMax(Node* insertNode)
{
int pos = ++Trees.
size;
for (; Trees.tree[pos /
2]->weight < insertNode->weight; pos /=
2)
{
Trees.tree[pos] = Trees.tree[pos /
2];
}
Trees.tree[pos] = insertNode;
}
void insertMin(Node* insertNode)
{
int pos = ++Trees.
size;
for (; Trees.tree[pos /
2]->weight>insertNode->weight; pos /=
2)
{
Trees.tree[pos] = Trees.tree[pos /
2];
}
Trees.tree[pos] = insertNode;
}
Node* deleteMax()
{
int parent =
1, child =
1;
Node* maxNode = Trees.tree[
1];
Node* lastNode = Trees.tree[Trees.
size];
--Trees.
size;
for (
parent =
1;
parent *
2 <= Trees.
size;
parent = child)
{
child =
parent *
2;
if (child != Trees.
size)
if (Trees.tree[child]->weight < Trees.tree[child +
1]->weight)
++child;
if (lastNode->weight <= Trees.tree[
parent]->weight)
if (lastNode->weight>Trees.tree[child]->weight)
break;
else
Trees.tree[
parent] = Trees.tree[child];
}
Trees.tree[
parent] = lastNode;
return maxNode;
}
Node* deleteMin()
{
int parent =
1, child =
1;
Node* minNode = Trees.tree[
1];
Node* lastNode = Trees.tree[Trees.
size];
--Trees.
size;
for (
parent =
1;
parent *
2 <= Trees.
size;
parent = child)
{
child =
parent *
2;
if (child != Trees.
size)
if (Trees.tree[child]->weight > Trees.tree[child +
1]->weight)
++child;
if (lastNode->weight >= Trees.tree[
parent]->weight)
if (lastNode->weight<Trees.tree[child]->weight)
break;
else
Trees.tree[
parent] = Trees.tree[child];
}
Trees.tree[
parent] = lastNode;
return minNode;
}
int isFull()
{
if (Trees.
size == MAX_CAPACITY)
return 1;
else
return 0;
}
int isEmpty()
{
if (Trees.
size ==
0)
return 1;
else
return 0;
}
Node* CreateTree_a()
{
while (Trees.
size !=
1)
{
Node* one = deleteMin();
Node* two = deleteMin();
Node* newNode=new Node();
newNode->weight = one->weight + two->weight;
newNode->Leftchild=one;
newNode->Rightchild = two;
insertMin(newNode);
}
return Trees.tree[
1];
}
void preTraversal(Node* root)
{
cout << root->weight <<
' ';
if (root->Leftchild!=NULL)
preTraversal(root->Leftchild);
if (root->Rightchild!=NULL)
preTraversal(root->Rightchild);
}
int main()
{
int N;
Node
*flag = new Node();
Node
*hufftree=NULL;
flag->weight = -
1000;
flag->Leftchild = NULL;
flag->Rightchild = NULL;
Trees.
size =
0;
Trees.tree[
0] = flag;
cin >> N;
for (
int i =
0; i < N; i++)
{
Node* newnode=new Node();
cin >> newnode->weight;
newnode->Leftchild = NULL;
newnode->Rightchild = NULL;
insertMin(newnode);
}
preTraversal(CreateTree_a());
return 0;
}
转自
dalao博客