哈夫曼树带权路径长度c语言,【哈夫曼树】求结点的哈夫曼的带权路径长度

本文用C++采用顺序存储实现求哈夫曼树(即最小生成树)的带权路径长度

5aaa6b082d72

努力

下面来了解一下哈夫曼树的构造以及如何求带权路径长度:

哈夫曼树为带权路径长度最小的树

5aaa6b082d72

哈夫曼树

5aaa6b082d72

哈夫曼树的顺序存储

【问题描述】

已知输入一串正整数,正整数之间用空格键分开,请建立一个哈夫曼树,以输入的数字为叶节点,求这棵哈夫曼树的带权路径长度。

【输入形式】

首先输入正整数的个数,然后接下来为接下来的正整数,正整数个数不超过10个

【输出形式】

输出相应的权值

【样例输入】

5 4 5 6 7 8

【样例输出】

69

【样例说明】

【评分标准】

注意n个叶子结点的哈夫曼树共有2n-1个结点

用到以下自定义函数:

一、选择两个其双亲域为0且权值最小的结点,并返回他们在HT中的序号num1和num2:

先选出第一个最小的,再选第二个,我都不敢相信此函数是耗时最长的,可能由于太简单就不重视了,结果在这出现好多问题

void Select(HuffmanTree HT, int n, int *min1, int *min2)

{

//选出第一个最小值结点

for (int i = 1; i <= n; i++)

{

if (HT[i].parent == 0)

{

*min1 = i;

break;

}

}

for (int i = 1; i <= n; i++)

{

if ((HT[i].weight < HT[*min1].weight) && (HT[i].parent == 0))

{

*min1 = i;

}

}

//选出与第一个结点不重复的第二个最小值结点

for (int i = 1; i <= n; i++)

{

if ((HT[i].parent == 0) && (i != *min1))

{

*min2 = i;

break;

}

}

for (int j = 1; j <= n; j++)

{

if ((HT[j].weight < HT[*min2].weight) && (j != *min1) && (HT[j].parent == 0))

{

*min2 = j;

}

}

}

二、构造哈夫曼树(采用顺序存储):

//构造哈夫曼树

void CreateHuffmanTree(HuffmanTree &HT, int n)

{

if (n <= 1)

{

return;

}

int m = 2 * n - 1;

HT = new HTNode[m + 1];//0号单元未用

for (int i = 1; i <= m; i++)//将1-m号单元中的双亲,左孩子,右孩子的下标都初始化为0

{

HT[i].parent = 0;

HT[i].lchild = 0;

HT[i].rchild = 0;

}

for (int i = 1; i <= n; i++)//输入前n个单元中叶子结点的权值

{

cin >> HT[i].weight;

}

int min1;

int min2;

for (int i = n + 1; i <= m; i++)//通过n-1次选择修改,来创建哈夫曼树

{

Select(HT, i - 1, &min1, &min2);//在HT[k](1<=k<=i-1)中选择两个其双亲域为0且权值最小的结点,并返回他们在HT中的序号num1和num2

HT[min1].parent = i;//得到新结点,将双亲域由0变为i

HT[min2].parent = i;

HT[i].lchild = min1;//num1,num2分别作为i的左右孩子

HT[i].rchild = min2;

HT[i].weight = HT[min1].weight + HT[min2].weight;//i的权值为左右孩子权值之和

}

}

三、求权重和:

//求权重

int Weight(HuffmanTree HT, int n)

{

int sum = 0;

for (int i = 1; i <= n; i++)

{

int j = i;

int num = 0;//计算从叶子结点到根结点经过几条边

while (HT[j].parent != 0)//跟结点双亲域为0

{

j = HT[j].parent;

num = num + 1;

}

sum = sum + num * HT[i].weight;//求权重

}

return sum;

}

其实刚开始我是用C语言编的,不过我动态创建了一个数组后,它只让我访问下标为0的结点,后来改成C++用了引用类型,而且在C++中,在动态创建了一个数组后,千万不要用HT[i]->来指代结构体中的元素,应该用HT[i].来代替,这又是我碰到的一个小问题,希望对大家有所帮助。

(我试了一下C语言换成(*HT[i].)也无法运行出结果)

5aaa6b082d72

完整代码如下(附详细注释):

#include

using namespace std;

typedef struct HTNode

{

int weight;

int parent;

int lchild;

int rchild;

}HTNode, *HuffmanTree;

//选择两个其双亲域为0且权值最小的结点,并返回他们在HT中的序号num1和num2

void Select(HuffmanTree HT, int n, int *min1, int *min2)

{

//选出第一个最小值结点

for (int i = 1; i <= n; i++)

{

if (HT[i].parent == 0)

{

*min1 = i;

break;

}

}

for (int i = 1; i <= n; i++)

{

if ((HT[i].weight < HT[*min1].weight) && (HT[i].parent == 0))

{

*min1 = i;

}

}

//选出与第一个结点不重复的第二个最小值结点

for (int i = 1; i <= n; i++)

{

if ((HT[i].parent == 0) && (i != *min1))

{

*min2 = i;

break;

}

}

for (int j = 1; j <= n; j++)

{

if ((HT[j].weight < HT[*min2].weight) && (j != *min1) && (HT[j].parent == 0))

{

*min2 = j;

}

}

}

//构造哈夫曼树

void CreateHuffmanTree(HuffmanTree &HT, int n)

{

if (n <= 1)

{

return;

}

int m = 2 * n - 1;

HT = new HTNode[m + 1];//0号单元未用

for (int i = 1; i <= m; i++)//将1-m号单元中的双亲,左孩子,右孩子的下标都初始化为0

{

HT[i].parent = 0;

HT[i].lchild = 0;

HT[i].rchild = 0;

}

for (int i = 1; i <= n; i++)//输入前n个单元中叶子结点的权值

{

cin >> HT[i].weight;

}

int min1;

int min2;

for (int i = n + 1; i <= m; i++)//通过n-1次选择修改,来创建哈夫曼树

{

Select(HT, i - 1, &min1, &min2);//在HT[k](1<=k<=i-1)中选择两个其双亲域为0且权值最小的结点,并返回他们在HT中的序号num1和num2

HT[min1].parent = i;//得到新结点,将双亲域由0变为i

HT[min2].parent = i;

HT[i].lchild = min1;//num1,num2分别作为i的左右孩子

HT[i].rchild = min2;

HT[i].weight = HT[min1].weight + HT[min2].weight;//i的权值为左右孩子权值之和

}

}

//求权重

int Weight(HuffmanTree HT, int n)

{

int sum = 0;

for (int i = 1; i <= n; i++)

{

int j = i;

int num = 0;//计算从叶子结点到根结点经过几条边

while (HT[j].parent != 0)//跟结点双亲域为0

{

j = HT[j].parent;

num = num + 1;

}

sum = sum + num * HT[i].weight;//求权重

}

return sum;

}

int main()

{

int n;

cin >> n;

HTNode *HT;

HT = new HTNode[2 * n + 1];

CreateHuffmanTree(HT, n);

int sum = Weight(HT, n);

cout << sum;

return 0;

}

5aaa6b082d72

测试结果

5aaa6b082d72

越努力,越幸运

end~~~

  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值