构造哈夫曼树
每个节点的存储结构设计如下图:
哈夫曼树的存储表示代码:
// 哈夫曼树的存储表示
typedef struct
{
int weight;//节点的权值
int parent, lchild, rchild;//节点的双亲、左孩子、右孩子的下标
}HTNode,*HuffmanTree;
所需的select函数如下:
//构建select函数
void Select(HuffmanTree HT, int m, int* s1, int* s2)
{ //从这m个数里边选择最小的2个//把第一个进行标记就ok
int i;//从下标为1的位置开始计数
//int min=HT[1].weight;这里直接赋值不合理,假如第一次那个1就是最小被选选中,那么第2次还是被选中
int min1 = 1000;
int min2 = 1000;//规定一个特别大的数
for (i = 1; i <= m; i++)
{
if (HT[i].parent == 0 && min1 > HT[i].weight)
{
min1 = HT[i].weight;
*s1 = i;
}
}
for (i = 1; i <= m; i++)
{//注意这个I!=*s1标记min
if (i != (*s1) && HT[i].parent == 0)
if (HT[i].weight < min2)
{
min2 = HT[i].weight;
*s2 = i;
}
}
}
创建哈夫曼树的函数如下:
//创建哈夫曼树
void createHuffmanTree(HuffmanTree &HT, int n)
{
int s1, s2;
//构造哈夫曼树HT
if (n <=1)
{
return;
}
int m = 2 * n - 1;
HT = new HTNode[m + 1];
for (int i = 0; i <= m; i++)
{
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for (int i = 0; i <= n; i++)
{
cin >> HT[i].weight;
}
//初始化结束,开始创建哈夫曼树..
for (int i = n + 1; i <= m; i++)
{
Select(HT, i - 1, &s1, &s2);//调用select函数
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
}
输出哈夫曼树的函数
//输出哈夫曼树..
void outHuffmanTree(HuffmanTree HT, int n)
{
if (HT == NULL)
{
printf("无huffmantree\n");
}
int i;
printf("输出huffmantree表格\n");
printf("结点 weight parent lchild rchild\n");
for (i = 1; i < 2 * n; i++)
{
//是2n-1个结点,申请了2n个位置0-2n-1(这是2n个用1-2n-1)
printf("%2d %6d %6d %6d %6d\n", i, HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
}
}
完整的代码:
#include
using namespace std;
// 哈夫曼树的存储表示
typedef struct
{
int weight;//节点的权值
int parent, lchild, rchild;//节点的双亲、左孩子、右孩子的下标
}HTNode,*HuffmanTree;
//构建select函数
void Select(HuffmanTree HT, int m, int* s1, int* s2)
{ //从这m个数里边选择最小的2个//把第一个进行标记就ok
int i;//从下标为1的位置开始计数
//int min=HT[1].weight;这里直接赋值不合理,假如第一次那个1就是最小被选选中,那么第2次还是被选中
int min1 = 1000;
int min2 = 1000;//规定一个特别大的数
for (i = 1; i <= m; i++)
{
if (HT[i].parent == 0 && min1 > HT[i].weight)
{
min1 = HT[i].weight;
*s1 = i;
}
}
for (i = 1; i <= m; i++)
{//注意这个I!=*s1标记min
if (i != (*s1) && HT[i].parent == 0)
if (HT[i].weight < min2)
{
min2 = HT[i].weight;
*s2 = i;
}
}
}
//创建哈夫曼树
void createHuffmanTree(HuffmanTree &HT, int n)
{
int s1, s2;
//构造哈夫曼树HT
if (n <=1)
{
return;
}
int m = 2 * n - 1;
HT = new HTNode[m + 1];
for (int i = 0; i <= m; i++)
{
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for (int i = 0; i <= n; i++)
{
cin >> HT[i].weight;
}
//初始化结束,开始创建哈夫曼树..
for (int i = n + 1; i <= m; i++)
{
Select(HT, i - 1, &s1, &s2);//调用select函数
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
}
//输出哈夫曼树..
void outHuffmanTree(HuffmanTree HT, int n)
{
if (HT == NULL)
{
printf("无huffmantree\n");
}
int i;
printf("输出huffmantree表格\n");
printf("结点 weight parent lchild rchild\n");
for (i = 1; i < 2 * n; i++)
{
//是2n-1个结点,申请了2n个位置0-2n-1(这是2n个用1-2n-1)
printf("%2d %6d %6d %6d %6d\n", i, HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
}
}
int main()
{
int n;
HuffmanTree HT;
printf("下面进行huffmantree的创建\n请输入你想要输入的结点个数:\n");
cin >> n;
createHuffmanTree(HT, n);
printf("创建Huffman tree完成\n");
outHuffmanTree(HT, n);//HT里边的值就是那棵哈夫曼树的地址,这样就需要考虑之前的单链表,与2叉数的问题了
system(pause);
return 0;
}